【C語言】猜數遊戲

系統隨機產生四個不同的有序的數字 (從小到大排列),等待用戶輸入猜測的結果, 用A來表示數字正確且位置正確的個數 ,用B來表示數字正確但位置不正確的個數,給八次機會,猜中則遊戲成功,機會用完則遊戲失敗

分析:1.需要一個數組存放生成的隨機數,保證數據不重複且按從小到大排列

           2.需要另外一個數組存放用戶的猜測結果

           3.需要一個變量記錄已經猜了多少次

           4.將兩個數組進行比較,統計A和B的個數並告知用戶,方便其繼續猜

           5.當用戶全部猜中或機會用完時,遊戲結束,退出

 

我第一次得到題目時編寫的代碼如下:

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

int main(void) {

	//提示遊戲規則
	printf("****************************************************\n");
	printf("*********************遊戲規則***********************\n");
	printf("系統將隨機生成四個不同的有序數字(按從小到大排列)\n");
	printf("請輸入您猜測的四個數字\n");
	printf("用A表示數字正確且位置正確的個數\n");
	printf("用B表示數字正確但位置不正確的個數\n");
	printf("一共有八次機會\n");
	printf("****************************************************\n");


    //產生不同的隨機數
    srand(time(NULL));
    int number[4];
    number[0] = rand() %9+1;
    number[1] = rand() %9+1;
    number[2] = rand() %9+1;
    number[3] = rand() %9+1;
    while (number[1] == number[0]) {
        number[1] = rand() %9+1;
    }
    while (number[2] == number[1] || number[2] == number [0]) {
        number[2] = rand() %9+1;
    }
    while (number[3] == number[2] || number[3] == number [1] || number[3] ==number[0]) {
        number[3] = rand() %9+1;
    }
	//這一句是爲了檢查數據是否重複,真正編譯時應該刪掉
    printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);     
    
    
    //將隨機數按從小到大排列
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < i; j++)
        {
            if(number[i] < number[j]){
                number[i] = number[i] + number[j];
                number[j] = number[i] - number[j];
                number[i] = number[i] - number[j];
            }
        }  
    }
	 //這一句是爲了檢查數據是否正確排列,真正編譯時應該刪掉
    printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);  
       
    //輸入數據並判斷
    int guess[4];
    int count = 8;
    
    do{
        int countA = 0;
        int countB = 0;
    
	//提示用戶輸入數據
    printf("請輸入四個1~9的數字(每輸一個按一次回車):\n");
    for (int i = 0; i < 4; i++) {
        scanf("%d",&guess[i]);
        while (guess[i] < 1 || 9 < guess[i]) {
            printf("輸入數據有誤,請重新輸入\n");
            scanf("%d",&guess[i]);
        }
    }
    printf("%4d %4d %4d %4d\n",guess[0],guess[1],guess[2],guess[3]);
    
    //判斷數字、位置是否相同並計數
    for ( i = 0; i < 4; i++) {
        if (guess[i] == number[i]) {
            countA++;
            continue;
        }
        for (int j = 0; j < 4; j++) {
            if (i == j) {
                continue;
            } else if (guess[i] == number[j]){
                countB++;
            }
        }
    }
        printf("一共有 %dA,%dB\n",countA,countB);

        //判斷遊戲是否應該結束
        if (countA == 4) {
            printf("恭喜您!遊戲成功\n");
            getchar();
            getchar();
            exit(EXIT_SUCCESS);
        }
        count--;
        printf("還有%d次機會\n",count);
		printf("*******************************************\n");
    }while (count > 0);
    
    printf("次數用完,遊戲失敗\n");
	printf("正確數字爲:%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
	getchar();
	getchar();
    return 0 ;
 
}

這個代碼是存在很多不足的,我在經過這兩天學習之後,主要進行了四個修改。

1.產生不同的隨機數部分

這是整個代碼最傻的部分,我第一次編寫時考慮使用for循環比較下標來保證數據不重複,但一直沒辦法實現,所以用了一個很傻的方法來使它不重複,實際上是不可取的。後來發現可以通過與一個臨時變量比較來實現,代碼如下:

 //產生不同的隨機數
	srand(time(NULL));
    int number[4];
    
    for (int i = 0; i < 4; i++) {
        //定義一個temp存放隨機數
        int temp = rand() %9+1;
        
        //判斷是否爲第一個數
        if (i == 0) {
            //是第一個數,直接存放
            number[i] = temp;
        } else {
            
            //不是,將temp與先前的數進行比較
            for (int j = 0; j < i; j++) {
                if (number[j] == temp ) {
                    //相同,退出循環,重新生成temp
                    i--;
                    break;
                } else{
                    //不同,直接存放
                    number[i] = temp;
                }
            }
        }
    }
    
    printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);

用這個方法就不會顯得那麼傻,而且可以借鑑到其他地方

 

2.判斷數字、位置是否相同並計數部分

這一部分乍一看沒問題,其實可以更加簡化,也更方便理解,代碼如下:

        //判斷數字、位置是否相同並計數
        for (i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {            
                //判斷數字是否相同
                if (guess[i] == number[j]){
                    //數字相同,判斷位置是否相同
                    if (i == j) {
                        //位置相同,A+1
                        countA++;
                    } else{
                       //位置不同,B+1
                        countB++;
                    }
                }
            }
        }
        printf("一共有 %dA,%dB\n",countA,countB);
        

 

3.將隨機數按從小到大排列部分

這個部分主要是在兩個數據交換位置時,通過兩個數據相互加減的方法來交換雖然不需要引入第三個變量,但是增加了運算,使效率變低,也顯得不夠簡單,因此最後改爲引入第三個變量進行交換。

4.對countA、countB的定義部分

將 int countA和int countB放進了do...while循環中,造成了重複定義,這實際上是不夠嚴謹的,於是將這兩個變量的定義提到外部,並在循環的最後將其清零。

修改後的所有代碼如下:

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

int main(void) {
    
    //提示遊戲規則
    printf("****************************************************\n");
    printf("*********************遊戲規則***********************\n");
    printf("系統將隨機生成四個不同的有序數字(按從小到大排列)\n");
    printf("請輸入您猜測的四個數字\n");
    printf("用A表示數字正確且位置正確的個數\n");
    printf("用B表示數字正確但位置不正確的個數\n");
    printf("一共有八次機會\n");
    printf("****************************************************\n");
    
    
    //產生不同的隨機數
    srand(time(NULL));
    int number[4];
    
    for (int i = 0; i < 4; i++) {
        //定義一個temp存放隨機數
        int temp = rand() %9+1;
        
        //判斷是否爲第一個數
        if (i == 0) {
            //是第一個數,直接存放
            number[i] = temp;
        } else {
            
            //不是,將temp與先前的數進行比較
            for (int j = 0; j < i; j++) {
                if (number[j] == temp ) {
                    //相同,退出循環,重新生成temp
                    i--;
                    break;
                } else{
                    //不同,直接存放
                    number[i] = temp;
                }
            }
        }
    }
    //這一句是爲了檢查數據是否重複,真正編譯時應該刪掉
    printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
    
    //將隨機數按從小到大排列
    for( i = 0; i < 4; i++){
        for(int j = 0; j < i; j++)
        {
            if(number[i] < number[j]){
                //使用第三方變量更方便,也更有效率
                int temp = 0;
                temp = number[i];
                number[i] = number[j];
                number[j] = temp;
            }
        }
    }
    //這一句是爲了檢查是否正確排序,真正編譯時應該刪掉
    printf("%4d %4d %4d %4d\n",number[0],number[1],number[2],number[3]);
    
        
    //輸入數據並判斷
    int guess[4];
    int count = 8;
    int countA = 0;
    int countB = 0;
    
    do{
        /*
        int countA = 0;
        int countB = 0;   定義只定義一次,所以應該在外部定義
         */   
        
        //提示用戶輸入數據
        printf("請輸入四個1~9的數字:\n");
        for (int i = 0; i < 4; i++) {
            scanf("%d",&guess[i]);
            
            //判斷數據是否在1-9區間內
            while (guess[i] < 1 || 9 < guess[i]) {
                printf("輸入數據有誤,請重新輸入\n");
                scanf("%d",&guess[i]);
            }
        }
        printf("%4d %4d %4d %4d\n",guess[0],guess[1],guess[2],guess[3]);
        
        //判斷數字、位置是否相同並計數
        for (i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                //判斷數字是否相同
                if (guess[i] == number[j]){
                    //數字相同,判斷位置是否相同
                    if (i == j) {
                        //位置相同,A+1
                        countA++;
                    } else{
                        //位置不同,B+1
                        countB++;
                    }
                }
            }
        }
        printf("一共有 %dA,%dB\n",countA,countB);
        
        //判斷是否全部猜中
        //全部猜中,遊戲結束
        if (countA == 4) {
            printf("恭喜您!遊戲成功\n");
            getchar();
            getchar();
            exit(EXIT_SUCCESS);
        }
        
        //沒猜中,次數-1,A、B清零
        count--;
        countA = 0;
        countB = 0;
        printf("還有%d次機會\n",count);
    }while (count > 0);
    
    //機會用完,遊戲結束
    printf("次數用完,遊戲失敗。\n");
    getchar();
    getchar();
    return 0 ;
    
}

其實這個程序還有不完善的地方,比如說沒有考慮用戶輸入相同數字時的處理等,但題目所需要的功能已經實現,玩一玩還是挺有意思的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章