Javaプログラミング学習サイト ゆるゆるプログラミング

2021/03/31 公開

・神経衰弱

プログラムが勝手にカードをめくっていく神経衰弱ののプログラムを作成しました。

このプログラムでは、ランダムにカードをめくっていき、全てのペア(同じ数字)が揃うと終了します。また、1度めっくたカードは記憶しているので1枚目にオープンしたカードと同じ番号を記憶している場合は、必ずペアになるようにしています。

以下が、そのJavaのソースコードです。

ShinkeiSuijaku.java ← クリックしてダウンロードページに移動
001:    // 神経衰弱
002:    public class ShinkeiSuijaku {
003:    	// カードの状態を表す定数
004:    	final static int STATUS_HIDE = 0;	// 伏せられた状態
005:    	final static int STATUS_OPEN = 1;	// オープンの状態
006:    	final static int STATUS_PAIR = 2;	// 揃った状態
007:    
008:    	// カード番号を格納する配列
009:    	static int[] cards;
010:    
011:    	// カードの状態を格納する配列
012:    	static int[] statuses;
013:    
014:    	// オープンしたカードを記憶する配列
015:    	static int[] memory;
016:    
017:    
018:    	// カードの初期化
019:    	private static void initCards()
020:    	{
021:    		// カードを格納する配列
022:    		cards = new int[ 52 ];
023:    
024:    		// カードを配列に格納し、シャフルする
025:    		for ( int i = 0; i < cards.length; i++ )
026:    			cards[ i ] = ( i / 4 ) + 1;
027:    
028:    		for ( int i = 0; i < cards.length; ++ i ) {
029:    			// 0~(配列cardsの個数-1)の乱数を発生
030:    			int rnd = (int)( Math.random() * (double)cards.length );
031:    
032:    			// cards[ i ]とcards[ rnd ]を入れ替える
033:    			int w = cards[ i ];
034:    			cards[ i ] = cards[ rnd ];
035:    			cards[ rnd ] = w;
036:    		}
037:    	}
038:    
039:    
040:    	// 状態の初期化
041:    	private static void initStatuses()
042:    	{
043:    		statuses = new int[ 52 ];
044:    		// カードの状態を"隠された状態"にする
045:    		for ( int i = 0; i < statuses.length; i++ )
046:    			statuses[ i ] = STATUS_HIDE;
047:    	}
048:    
049:    
050:    	// 記憶の初期化
051:    	private static void initMemory()
052:    	{
053:    		memory = new int[ 52 ];
054:    		for ( int i = 0; i < memory.length; i++ )
055:    			memory[ i ] = 0;
056:    	}
057:    
058:    
059:    	// カードの出力
060:    	private static void outputCards()
061:    	{
062:    		for ( int i = 0; i < cards.length; ++ i ) {
063:    			//
064:    			switch ( statuses[ i ] ) {
065:    				case STATUS_HIDE:
066:    					System.out.print( "*" );
067:    					break;
068:    
069:    				case STATUS_OPEN:
070:    				case STATUS_PAIR:
071:    					switch ( cards[ i ] )
072:    					{
073:    						case 10:
074:    							System.out.print( "A" );
075:    							break;
076:    						case 11:
077:    							System.out.print( "J" );
078:    							break;
079:    						case 12:
080:    							System.out.print( "Q" );
081:    							break;
082:    						case 13:
083:    							System.out.print( "K" );
084:    							break;
085:    
086:    						default:
087:    							System.out.print( cards[ i ] );
088:    							break;
089:    					}
090:    					break;
091:    			}
092:    
093:    			// カード13枚ごとに改行
094:    			if ( 0 == ( ( i + 1 ) % 13 ) )
095:    				System.out.println();
096:    		}
097:    		// 改行
098:    		System.out.println();
099:    	}
100:    
101:    
102:    	// 指定した状態の数を戻す
103:    	private static int getStatusNumber( int status  )
104:    	{
105:    		int number = 0;
106:    
107:    		for ( int i = 0; i < statuses.length; i++ ) {
108:    			if ( statuses[ i ] == status )
109:    				++ number;
110:    		}
111:    
112:    		return number;
113:    	}
114:    
115:    
116:    	// カードを1枚オープン
117:    	private static int openCard()
118:    	{
119:    		// 伏せられたカードの数を取得
120:    		int hidenumber = getStatusNumber( STATUS_HIDE );
121:    		if ( 1 > hidenumber ) return 0;
122:    
123:    		// 1~hidenumberの乱数を発生
124:    		int rnd = (int)( Math.random() * (double)hidenumber ) + 1;
125:    
126:    		// 伏せられたカードのrnd番目のカードをオープン
127:    		int cardnum = 0;
128:    		for ( int i = 0; i < statuses.length; i++ ) {
129:    			if ( STATUS_HIDE == statuses[ i ] ) {
130:    				--rnd;			
131:    				if ( 0 == rnd ) {
132:    					// 状態を"オープンの状態"に変更
133:    					statuses[ i ] = STATUS_OPEN;
134:    					// カード番号を代入
135:    					cardnum = cards[ i ];
136:    					//記憶を登録
137:    					memory[ i ] = cardnum;
138:    					break;
139:    				}
140:    			}
141:    		}
142:    
143:    		// オープンしたカード番号を戻す
144:    		return cardnum;
145:    	}
146:    
147:    
148:    	// 記憶したカード番号で隠されているカードをオープン
149:    	private static boolean openMemoryCard( int cardnum )
150:    	{
151:    		for ( int i = 0; i < statuses.length; i++ ) {
152:    			if ( STATUS_HIDE == statuses[ i ] ) {
153:    				if ( cardnum == memory[ i ] ) {
154:    					// 状態を"オープンの状態"に変更
155:    					statuses[ i ] = STATUS_OPEN;
156:    					return true;
157:    				}
158:    			}
159:    		}
160:    
161:    		return false;
162:    	}
163:    
164:    
165:    	// "オープン状態"の2枚のカード番号が同じかを判定	
166:    	private static boolean isPair()
167:    	{
168:    		int number, cardnum;
169:    
170:    		number = 0;
171:    		cardnum = 0;
172:    		for ( int i = 0; i < statuses.length; i++ ) {
173:    			if ( STATUS_OPEN == statuses[ i ] ) {
174:    				++ number;
175:    				if ( 1 == number ) {
176:    					// 1枚目
177:    					cardnum = cards[ i ]; 
178:    				}
179:    				else {
180:    					// 2枚目
181:    					if ( cardnum == cards[ i ] ) {
182:    						return true;
183:    					}
184:    					break;
185:    				}
186:    			}
187:    		}
188:    
189:    		return false;
190:    	}
191:    
192:    
193:    	// 状態の変更(旧状態→新状態)
194:    	private static void replaceStatus( int oldStatus, int newStatus )
195:    	{
196:    		for ( int i = 0; i < statuses.length; i++ ) {
197:    			if ( oldStatus == statuses[ i ] )
198:    				statuses[ i ] = newStatus;
199:    		}
200:    	}
201:    	
202:    
203:    	// メイン
204:    	public static void main( String[] args ) {
205:    		// カードの初期化
206:    		initCards();
207:    
208:    		// 状態の初期化
209:    		initStatuses();
210:    
211:    		// 記憶の初期化
212:    		initMemory();
213:    
214:    		// 神経衰弱本体
215:    		// 無限ループを作成(ループを抜ける条件をなし)
216:    		for ( int turn = 1; ; ++ turn ) {
217:    			// ターン番号の出力
218:    			System.out.println( "ターン:" + turn );
219:    
220:    			// カードを出力(オープン前の状態)
221:    			outputCards();
222:    
223:    			// カードをランダムに1枚オープン
224:    			int cardnum1 = openCard();
225:    
226:    			// 記憶しているカードがあればそのカードをオープン
227:    			if ( !openMemoryCard( cardnum1 ) ) {
228:    				// カードをランダムに1枚オープン
229:    				int cardnum2 = openCard();
230:    			}
231:    			else {
232:    				System.out.println( "記憶からカードをオープン!" );
233:    			}
234:    
235:    			// カードを出力(オープン後の状態)
236:    			outputCards();
237:    
238:    			// オープンしているカードがペアかどうか判定
239:    			if ( isPair() )
240:    				replaceStatus( STATUS_OPEN, STATUS_PAIR );
241:    			else
242:    				replaceStatus( STATUS_OPEN, STATUS_HIDE );
243:    
244:    			// 全てペアになったらループを抜ける
245:    			if ( 52 == getStatusNumber( STATUS_PAIR ) )
246:    				break;
247:    		}
248:    
249:    		// カードの最終結果を出力
250:    		System.out.println( "最終結果" );
251:    		outputCards();
252:    	}
253:    }

ソースコードの解説はこちらです。「神経衰弱 その2」

ShinkeiSuijaku.javaの出力結果

ターン:1
*************
*************
*************
*************

*************
*5***********
*************
**2**********

ターン:2
*************
*************
*************
*************

*************
*5*********4*
*************
*************

     :

ターン:15
***2*K*7*****
*5**5******44
*4*7K*******4
**2**********

記憶からカードをオープン!
**32*K*7*****
*5**5****3*44
*4*7K*******4
**2**********

ターン:16
**32*K*7*****
*5**5****3*44
*4*7K*******4
**2**********

*132*K*7*****
*5**5****3*44
*4*7K*******4
**2*********9

     :

ターン:46
8132JKK7921AK
55*75Q1593344
24Q7K6JA6A634
812J*J6AQ7Q99

記憶からカードをオープン!
8132JKK7921AK
55875Q1593344
24Q7K6JA6A634
812J8J6AQ7Q99

最終結果
8132JKK7921AK
55875Q1593344
24Q7K6JA6A634
812J8J6AQ7Q99

ソースコードの解説はこちらです。「神経衰弱 その2」

■関連コンテンツ

神経衰弱 その2 1人で神経衰弱
ポーカーの役判定 ポーカーの役を判定
トランプの操作 トランプを操作するクラス
配列の並び替え 配列をランダムに並び替える方法を解説
switch文 式による処理の分岐に使用するswitch文について解説
値のコンソール表示 print()、println()とは?
Math.randomの使い方について解説-画像

乱数 random

Math.randomメソッドを使って乱数を発生する方法を解説します。指定範囲の乱数の発生方法も解説しています。

サイコロの目のでる確率は?-画像

サイコロの出目確率

乱数で1から6の数を発生し、それぞれの数値が出現する回数を調べます。

サイコロの目のでる確率は?-画像

ゾロ目の出る確率

2つのサイコロの出目を乱数で1から6の数を発生し、出目が同じときの回数と出現率を調べます。

繰り返し処理に使用するfor文について解説-画像

for文

繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。

条件による処理の分岐に使用するif文について解説-画像

if文

条件による処理の分岐に使用するif文について解説

■新着情報

2022.07.06 完全数 6=1+2+3

■広告

 

 

 

 

 

スッキリわかるJava入門第3版 [ 中山清喬 ]

価格:2,860円
(2021/6/18 14:32時点)
感想(6件)

 

 

 

 

Topへ