ヒットアンドブローで悩んでいます

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アリス

ヒットアンドブローで悩んでいます

#1

投稿記事 by アリス » 12年前

ヒットアンドブローで悩んでいるのですが
コンピュータがプレイヤーの入力したヒット数とブロー数の合計からプレイヤーの4桁の数値を導きだす関数を作成したのですが
上手くいかず求めることはできるのですが大分コンピュータのターンが必要です。本当なら数ターンで導き出せるのですがどうしたらいいでしょうか。
内容としてはコンピュータが表示した4桁の数値に対し、プレイヤーが入力したヒット数、ブロー数から重複しない4桁と比較し可能性のある数値から最小値を表示し可能性のない数値を配列から削除したいのです。また、プレイヤーが不正な数値(2回連続0ヒット0ブロー)が入力されるとエラーを表示させたいのです。

また、再プレイした際コンピュータがプレイヤーの数値を乱数を使って表示するのですが重複していたりします。
これを防ぐにはどうしたらいいでしょうか。

分かる方参考にしたいのでよろしくお願いします。


コード:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include<string.h>
#include<ctype.h>


char number[5040][5];

void func(char[5040][5] , int* , char* , int);


数値の照合関数。ここから
void hitandblow(const char *x , const char *y);


void expect(char *x , char[5040][5],int hit , int blow);


int main(void) {

 //コンピュータの4桁の数値を決める際使用
char cpu_answer[] = "0123456789";
 char cpu_number[] = "0123456789";
 int randam1 = 0;
 int randam2 = 0;
 char w;

 //リトライするかしないかの際使用
int retry = 0;
 char input_retry[3];

 //人がコンピュータの4桁の数値を当てる際に使用
int i = 0;
 int j = 0;
 char player_answer[6];
 int player_hit = 0, player_blow = 0;

 //コンピュータが人の4桁の数値を求める際最初の1回目は乱数それ以降は数値の予想をする。
int cpu_turn = 0;
 int a = 0; 

 //エラーを表示する際使用
int error = 0;

 //数値の長さを求める際使用
int length = 0;

 //先手後手を決める
char input_turn[3];
 int turn = 0;

 //人がコンピュータの4桁の数値を当てる際に使用
char input_hit[3];
 char input_blow[3];
 int cpuhit = 0;//文字列input_hitに入れられた文字を数値に変換する際使用
int cpublow = 0;//文字列input_blowに入れられた文字を数値に変換する際使用

char data[5] = { 0 };
 int cntr = 0;





 //重複しない全ての4桁の数値を「number」へ格納
func(number , &cntr ,data , 1);

 //全パターン分繰り返す
// for(i = 0 ; i < 5040 ; i++)
// {
// printf("%s\n" , number[i]);

// }

// if(!strcmp(number[ i ] , "1234"));
// {
// //配列の何番目かを表示
// printf("一致:number[%d] == \"1234\"\n" , i);
// }




 printf("ヒットアンドブローを開始します\n");

 /* 乱数系列を初期化 */
srand((unsigned int)time(NULL));




 /* 全体のループ */

while (1){ // 1ゲーム分のループ 

while(1){ //先手後手を決める
printf("先手か後手のどちらにしますか(先手・・・1, 後手・・・2) ");

 fgets( input_turn, sizeof(input_turn)+1, stdin );
 //文字列(sentegote)の中にNULLが存在しない場合、以降の領域を侵してでもNULLを探すのでNULLを配列の末尾に入れる。
input_turn[strlen(input_turn)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n", input_turn, strlen(input_turn) );

 error = 0;

 //入力した値が1桁かチェックする
length = strlen(input_turn);
 if (length != 1){
 error = 1;
 }


 //入力された値が「0」以下または、「3」以上が入れられた場合
if (input_turn[0] <= '0' || input_turn[0] >= '3' ){
 error = 1;

 }

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した値が正しくありません。再入力してください。\n"); 
 /* 入力文字数がサイズオーバーしてると標準入力(stdin)にゴミが残るのでクリア */
fflush( stdin );

 continue;


 }
 //配列に入れられた値を数値に変換する。
turn = atoi(input_turn);

 if (turn == 1){
 printf("あなたが先手です。\n");
 break;
 }
 else if(turn == 2){
 printf("あなたが後手です。\n");
 break;
 } 
 }

 //コンピュータ側の4桁の数値を決める。 
printf("コンピュータの数値を作成しています。\n"); 


 /* コンピュータ側の4数字をシャッフルする */
for (i = 0; i < 100; i++) { 
 randam1 = rand() % 10;
 randam2 = rand() % 10;
 w = cpu_answer[randam1];
 cpu_answer[randam1] = cpu_answer[randam2];
 cpu_answer[randam2] = w; /* 入れ替え */ 
 }

printf("%.4s\n" , cpu_answer); //CPU側の0~9の数字をシャッフルし4桁までの数字を表示


//ヒットが4になるまで繰り返す
while(1){

 //人が先手だった時。
if (turn == 1){ 

 printf("あなたが予想するコンピュータの4桁の数値を入力してください。\n");
 fgets( player_answer, sizeof(player_answer)+1, stdin );
 player_answer[strlen(player_answer)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n\n", hito4keta, strlen(hito4keta));
 error = 0;

 //入力した値が4桁かチェックする
length = strlen(player_answer);
 if (length != 4){
 error = 1;
 }

 //入力データが数値かチェック
for (i = 0; i < length; i++){
 if (isdigit(player_answer[i]) == 0){
 error = 1;
 }
 }

 //重複していないかチェックする
for (i = 0; i < length; i++){
 for (j = i + 1; j < length; j++){
 if (player_answer[i] == player_answer[j]){
 error = 1;
 }
 }
 }

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した数値が正しくありません。\n再入力してください。\n");
 fflush( stdin );

 continue;

 }

 /* ヒット数とブロー数を算出する */

hitandblow(cpu_answer, player_answer);



 for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (player_answer[i] == cpu_answer[j]) {
 if (i == j) {
 player_hit++;
 }
 else{
 player_blow++;
 }
 }
 }
 }

 /* 人のターン */
if (player_hit != 4){
 turn = 2;/*順番入れ替え*/
printf("回答者と出題者が交代します。\n");
 printf("コンピュータの番です。\n");
 player_hit = 0;
 player_blow = 0;
 }
 else{
 break;
 }

 }
 //コンピュータが先手の場合。
else if (turn == 2){

 /*コンピュータは初めの一回は乱数を使って人側の4桁の数字を表示する。。*/
if (cpu_turn == 0){

 printf("私が予想するあなたの4桁の数値は\n");

 for (i = 0; i < 100; i++) { 
 randam1 = rand() % 10;
 randam2 = rand() % 10;
 w = cpu_number[randam1];
 cpu_number[randam1] = cpu_number[randam2];
 cpu_number[randam2] = w; /* 入れ替え */
 }

printf("%.4s" , cpu_number);//乱数を使って0~9の数字をシャッフルし4桁までを表示させる。
printf("です。\n");

 while(1){//算出された数値に対してのヒット、ブローの入力

while (1){//ヒットの入力
printf("ヒットとブローの数を入力してください。\n"); 
 printf("ヒット:");
fgets( input_hit, sizeof(input_hit)+1, stdin );
 input_hit[strlen(input_hit)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n", cpuhit1, strlen(cpuhit1) );
 error = 0;

 //入力した値が1桁かチェックする
length = strlen(input_hit);
 if (length != 1){
 error = 1;
 }


 //入力された値が「0」より小さい値または、「5」以上の値が入れられた場合
if (input_hit[0] < '0' || input_hit[0] >= '5' ){
 error = 1;

 }

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した値が正しくありません。再入力してください。\n\n");
 fflush( stdin );
 }
 else{
 cpuhit = atoi(input_hit);//ヒットに入った文字を数値に変換
break;
 }
 }

 while(1){//ブローの入力
printf("ブロー:");

fgets( input_blow, sizeof(input_blow)+1, stdin );
 input_blow[strlen(input_blow)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n", cpublow1, strlen(cpublow1) );

 error = 0;

 //入力した値が1桁かチェックする
length = strlen(input_blow);
 if (length != 1){
 error = 1;
 }

 //入力された値が「0」より小さい値または、「5」以上の値が入れられた場合
if (input_blow[0] < '0' || input_blow[0] >= '5' ){
 error = 1;
 }

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した値が正しくありません。再入力してください。\n\n");
 fflush( stdin );
 }

 else{
 cpublow = atoi(input_blow);//ブローに入った文字を数値に変換
break;
 }
 }

 if (cpuhit + cpublow > 4){//ヒットとブローの入力された数値を計算し合計が4より大きければ再入力
printf("ヒットとブローの合計値が4以上です。再入力してください。\n");
 fflush( stdin );
 }
 else if (cpuhit == 3 && cpublow >= 1){
 printf("ヒットとブローの値がおかしいです。再入力してください。\n");
 fflush( stdin );
 }
 else{
 break;
 }
 }

 if (cpuhit != 4){//ヒットが4でなければ回答者と出題者を入れ替える
printf("回答者と出題者を入れ替えます\n");
 printf("あなたの番です。\n\n");
 cpu_turn = 1;//回数を1にして次からは予想関数でヒットとブローを求める。
} 
else{
 break;
 }
 }
 else if (cpu_turn == 1){/*コンピュータは2回目からは数値の予想関数を使って求めていく*/

 //printf("コンピュータの数値の予想関数使用\n\n");

 expect(cpu_number , number ,cpuhit , cpublow);

 while (1){//算出された数値に対してのヒット、ブローの入力

while (1){//ヒットの入力
printf("ヒットとブローの数を入力してください。\n");
 printf("ヒット:");
fgets( input_hit, sizeof(input_hit)+1, stdin );
 input_hit[strlen(input_hit)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n", cpuhit1, strlen(cpuhit1) );
 error = 0;

 //入力した値が1桁かチェックする
length = strlen(input_hit);
 if (length != 1){
 error = 1;
 }


 //入力された値が「0」より小さい値または、「5」以上の値が入れられた場合
if (input_hit[0] < '0' || input_hit[0] >= '5' ){
 error = 1;

 }

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した値が正しくありません。再入力してください。\n");
 fflush( stdin );
 }
 else{
 cpuhit = atoi(input_hit);//ヒットに入った文字を数値に変換
break;
 }
 }

 while(1){//ブローの入力
printf("ブロー:");
fgets( input_blow, sizeof(input_blow)+1, stdin );
 input_blow[strlen(input_blow)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n", sentegote, strlen(sentegote) );
 error = 0;

 //入力した値が1桁かチェックする
length = strlen(input_blow);
 if (length != 1){
 error = 1;
 }


 //入力された値が「0」より小さい値または、「5」以上の値が入れられた場合
if (input_blow[0] < '0' || input_blow[0] >= '5' ){
 error = 1;

 } 

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した値が正しくありません。再入力してください。\n");
 fflush( stdin );
 }
 else{
 cpublow = atoi(input_blow);//ブローに入った文字を数値に変換
break;
 }

 }

 if (cpuhit + cpublow > 4){//ヒットとブローの入力された数値を計算し合計が4より大きければ再入力
printf("ヒットとブローの合計値が4以上です。\n");
 }
 else{
 break;
 }
 }

 if (cpuhit != 4){//ヒットが4でなければ回答者と出題者を入れ替える
printf("回答者と出題者を入れ替えます\n");
 printf("あなたの番です。\n");
 }
 else{
 break;
 }
 }
 turn = 1;/*順番入れ替え*/
cpu_turn = 1;/**機械の場合2回目からは数値の予想関数を使用する。*/
 }

 } /*人かコンピュータかどちらかのヒットが4になるまで繰り返す */

if (turn == 1){/*turn = 1 ・・人がコンピュータのヒットを当てたら*/
printf("あなたが勝ちました。おめでとうございます。\n");

 }
 else if (turn == 2){/*turn = 2 ・・コンピュータが人のヒットを当てたのなら。*/
printf("コンピュータが勝ちました。次は頑張ってください\n");
 }

 while(1){

 /* 再プレイするかどうか聞く */
printf("再プレイしますか(yes・・1 , no・・2) ");
 fgets( input_retry, sizeof(input_retry)+1, stdin );
 input_retry[strlen(input_retry)-1] = '\0';
 //printf( "入力文字列:[%s] 入力文字数:[%d]\n", ritorai, strlen(ritorai) );
 error = 0;

 //入力した値が1桁かチェックする
length = strlen(input_retry);
 if (length != 1){
 error = 1;
 }

 //入力データが数値かチェック
if (isdigit(input_retry[0]) == 0){
 error = 1;
 }

 //入力された値が「0」以下または、「3」以上が入れられた場合
if (input_retry[0] <= '0' || input_retry[0] >= '3' ){
 error = 1;

 }

 //error == 1ならエラー表示する
if (error == 1){
 printf("入力した値が正しくありません。1か2を入力してください。\n");
 fflush( stdin ); 
 }
 else{
 retry = atoi(input_retry);//ritoに入った文字を数値に変換する。
break;
 }

 }

 if (retry == 1){
 printf("ヒットアンドブローを再プレイします。\n\n");
 fflush( stdin );
 cpu_turn = 0;
 player_hit = 0;

 // for(i = 0 ; i < 1 ; i++){
 // for(j = 0 ; j < 4 ; j++){
 // cpu_number[i] = j;
 // }
 // }



 }
 else {
 break;
 }

 } // リトライするなら繰り返ししなければ終了する。 

/* 終了 */
printf("ヒットアンドブローを終了します。\n");

 return 0;
}

//数値の照合関数。ここから
void hitandblow(const char *x , const char *y)
{
 int i = 0;
 int j = 0;
 int hit=0;
 int blow=0;

 for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (x[i] == y[j]) {
 if (i == j) {
 hit++;
 }
 else {
 blow++;
 }
 }
 }
 }
 printf("あなたが入力した4桁の数値は\n");
 printf("ヒット数:%d ブロー数:%d" ,hit , blow );
 printf("です。\n");
}
//数値の照合関数。ここまで


// 重複しない全ての4桁の数値を「number」へ格納する関数
void func(char pnumber[5040][5] , int* pcntr , char* pdata , int pos)
{
 char i , *p;
 int j;

 p = &pdata[pos - 1];
 for(i = 0 ; i < 10 ; i++){

 for(j = 0 ; j <= 4 ; j++){

 if('0' + i == pdata[ j ]){
 break;
 }
 }
 if(j < 4){
 continue;
 }
 *p = '0' + i;

 if(4 == pos ){
 strcpy( pnumber[ ( *pcntr )++ ], pdata );
 }
 else{
 func(pnumber , pcntr , pdata , pos + 1);
 }
 }
 *p = '\0';
}




//コンピュータの数値の予想関数。ここから。
void expect( char *x, char pnumber[5040][5] ,int hit , int blow)
{

 int i = 0;
 int j = 0;
 int k = 0;

 int l = 0;
 int m = 0;
 int n = 0;
 int o = 0;

 char *cpu_answer[5040];
 static int turn = 0;

 int player_hit = 0;
 int player_blow = 0;


 //printf("%s\n" , x);
 //printf("%s\n" , pnumber);


 if(hit + blow == 0){

 for(k = 0 ; k < 5040 ; k++){//重複しない全ての4桁の数値と比較する(5040通り)
for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (x[i] == pnumber[k][j]) {
 if (i == j) {
 player_hit++;
 }
 else {
 player_blow++;
 }
 }
 }
 }


 if(player_hit == 4){

 }

 else if(player_hit + player_blow == 0){
 cpu_answer[m] = pnumber[k];
 m++;
 }

 //printf("%.4s %s\n" , x , pnumber[k]);
 //printf("ヒット数:%d , ブロー数%d\n" , player_hit , player_blow);

 player_hit = 0;
 player_blow = 0;
 }

 printf("あなたの数値は%sですか?\n" ,cpu_answer[0] );
 }

 if(hit + blow == 1){

 for(k = 0 ; k < 5040 ; k++){
 for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (x[i] == pnumber[k][j]) {
 if (i == j) {
 player_hit++;
 }
 else {
 player_blow++;
 }
 }
 }
 }

 if(player_hit == 4){

 }
 else if(player_hit + player_blow == 1){ 
 cpu_answer[m] = pnumber[k];
 m++;
 }

 //printf("数値は%sですか\n" , cpu_answer[0]);

 //printf("%.4s %s\n" , x , pnumber[k]);
 //printf("ヒット数:%d , ブロー数%d\n" , player_hit , player_blow);

 player_hit = 0;
 player_blow = 0;
 }

 printf("あなたの4桁の数値は%sですか?\n" ,cpu_answer[0] );
 }

 if(hit + blow == 2){
 for(k = 0 ; k < 5040 ; k++){
 for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (x[i] == pnumber[k][j]) {
 if (i == j) {
 player_hit++;
 }
 else {
 player_blow++;
 }
 }
 }
 }

 if(player_hit == 4){

 }
 else if(player_hit + player_blow == 2){ 
 cpu_answer[m] = pnumber[k];
 m++;
 }

 // printf("%.4s %s\n" , x , pnumber[k]);
 // printf("ヒット数:%d , ブロー数%d\n" , player_hit , player_blow);

 player_hit = 0;
 player_blow = 0;
 }

 printf("あなたの4桁の数値は%sですか?\n" ,cpu_answer[0] );
 }

 if(hit + blow == 3){

 for(k = 0 ; k < 5040 ; k++){
 for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (x[i] == pnumber[k][j]) {
 if (i == j) {
 player_hit++;
 }
 else {
 player_blow++;
 }
 }
 }
 }

 if(player_hit == 4){

 }
 else if(player_hit + player_blow == 3){
 cpu_answer[m] = pnumber[k];
 m++;
 }

 // printf("%.4s %s\n" , x , pnumber[k]);
 // printf("ヒット数:%d , ブロー数%d\n" , player_hit , player_blow);

 player_hit = 0;
 player_blow = 0;
 }

 printf("あなたの4桁の数値は%sですか?\n" ,cpu_answer[0] );

 }

 if(hit + blow == 4){

 for(k = 0 ; k < 5040 ; k++){
 for (i = 0; i < 4; i++) {
 for (j = 0; j < 4; j++) {
 if (x[i] == pnumber[k][j]) {
 if (i == j) {
 player_hit++;
 }
 else {
 player_blow++;
 }
 }
 }
 }

 if(player_hit == 4 ){//前回の4桁と今回比較する数値が同じ場合、cpu_answreに4桁の数値を格納しない

}
else if(player_hit + player_blow == 4 ){
 cpu_answer[m] = pnumber[k];
 m++;
 }


 player_hit = 0;
 player_blow = 0;
 }

 printf("あなたの4桁の数値は%sですか?\n" ,cpu_answer[0] ); 

 }

 //可能性のある4桁の数値を格納
for(i = 0 ; i < m ; i++){
 for(j = 0 ; j < 4 ; j++){
 pnumber[i][j] = cpu_answer[i][j];
 }
 }

 strcpy(x, *pnumber);
 //最小値の数値として表示した4桁の数値を次回比較する対象の数値に変更する。
printf("%s\n" , x);

 //printf("%s\n" , x[0]);
 //printf("%s\n" , pnumber[1]);

}
//コンピュータの数値の予想関数。ここまで。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: ヒットアンドブローで悩んでいます

#2

投稿記事 by みけCAT » 12年前

似たコードがここにあります。
http://dixq.net/forum/viewtopic.php?f=3&t=15174
同じ学校のテンプレートですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ヒットアンドブローで悩んでいます

#3

投稿記事 by softya(ソフト屋) » 12年前

フェルトさんですね。
この掲示板では同じ名前を使用して頂くようにお願いしております。
元のトピックがありますので、そちらでお続けください。
こちらは不要ですので閉鎖しておきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る