200行C語(yǔ)言代碼實(shí)現(xiàn)簡(jiǎn)易三子棋游戲
前言
三子棋應(yīng)該是是我們最早接觸到的棋類游戲,用C語(yǔ)言實(shí)現(xiàn)三子棋對(duì)初學(xué)者來說是一種不錯(cuò)的鍛煉
編寫三子棋只需要用到數(shù)組、函數(shù)和生成隨機(jī)數(shù)的知識(shí),所以比較適合成為編程學(xué)習(xí)者編寫的第一個(gè)小游戲。
一.代碼實(shí)現(xiàn)
第一部分是源碼復(fù)制就可以使用,每一個(gè)自定義函數(shù)在第二部分設(shè)計(jì)思路中都有詳細(xì)解釋,結(jié)合代碼實(shí)現(xiàn)和設(shè)計(jì)思路理解會(huì)有一個(gè)更好的效果
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include<time.h> #include<stdlib.h> #define ROW 3 #define COL 3 void reset(char arr[ROW][COL])//將棋盤arr[ROW][COL]數(shù)據(jù)賦值為空格 { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { arr[i][j] = ' '; } } } void dis_play(char arr[ROW][COL])//打印棋盤 { for (int i = 0; i < ROW; i++)//for每一次進(jìn)去,打印一行數(shù)組和一條分割線 { //數(shù)組行為:(空格)元素(空格)|(空格)元素(空格)|(空格)元素(空格) //分割線為: - - - | - - - | - - - for (int j = 0; j < COL; j++)//一行數(shù)組 { printf(" %c ", arr[i][j]); if (j < COL - 1)//為了美觀,最后的“|”不打印 { printf("|"); } } printf("\n"); for (int k = 0; k < COL; k++)//一行分割線 { printf("---"); if (k < COL - 1)//為了美觀,最后的“|”不打印 { printf("|"); } } printf("\n"); } } void player_move(char arr[ROW][COL])//玩家下棋 { int row = 0, col = 0; while (1) { printf("玩家下棋,請(qǐng)輸入坐標(biāo)>:"); scanf("%d %d", &row, &col); if (arr[row - 1][col - 1] == ' ')//判斷是否可以下棋 { arr[row - 1][col - 1] = '*'; break; } printf("輸入錯(cuò)誤,請(qǐng)?jiān)俅屋斎隲n"); } } void computer_move(char arr[ROW][COL])//電腦下棋 { int row = rand() % ROW;//生成行號(hào) int col = rand() % COL;//生成列標(biāo) printf("電腦下棋:>\n"); while (1) { if (arr[row][col] == ' ')//判斷是否可以下棋 { arr[row][col] = '#'; break; } row = rand() % ROW; col = rand() % COL; } } int is_full(char arr[ROW][COL])//用于在is_win()中判斷是否為平局 { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (arr[i][j] == ' ') return 0; } } return 1; } char is_win(char arr[ROW][COL])//三子棋勝利無非就三種情況:行相同、列相同和對(duì)角線相同。除開勝利還有平局 { for (int i = 0; i < ROW; i++)//判斷行 { if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ') return arr[i][0]; } for (int i = 0; i < COL; i++)//判斷列 { if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ') return arr[0][i]; } //判斷對(duì)角線 if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ') return arr[0][0]; if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[0][2] != ' ') return arr[0][2]; //判斷平局 if (is_full(arr)) { return 'q'; } //都不滿足游戲繼續(xù)運(yùn)行 return ‘c' return 'c'; } void meau() { printf("------------------\n"); printf("| 1.play |\n"); printf("|----------------|\n"); printf("| 0.exit |\n"); printf("------------------\n"); } void game() { char arr[ROW][COL];//初始化棋盤 char ch; reset(arr);//將棋盤里每一個(gè)元素賦值為空格 dis_play(arr); do { player_move(arr); dis_play(arr); ch=is_win(arr); if (ch != 'c') { break; } computer_move(arr); dis_play(arr); ch=is_win(arr); if (ch != 'c') { break; } } while (1); switch (ch)//根據(jù)返回字符判斷結(jié)果 { case '#': printf("電腦勝利\n"); break; case '*': printf("玩家勝利\n"); break; case 'q': printf("平局\n"); break; } } int main() { srand((unsigned)time(NULL)); int input = 0; do { meau(); scanf("%d", &input); switch (input) { case 1 : game(); break; case 0 : break; default : printf("輸入錯(cuò)誤\n"); } } while (input); return 0; }
二.設(shè)計(jì)思路
main()函數(shù)搭建框架
1.main()函數(shù)搭建框架:像所有的電腦游戲一樣,我們需要一個(gè)菜單,通過菜單選擇進(jìn)入游戲和退出游戲,當(dāng)一盤游戲結(jié)束時(shí)可以再次選擇進(jìn)入或者退出,菜單用printf()打印就可以解決,循環(huán)的進(jìn)入游戲用do while()循環(huán)就可以解決
實(shí)現(xiàn)代碼如下
void meau() { printf("------------------\n"); printf("| 1.play |\n"); printf("|----------------|\n"); printf("| 0.exit |\n"); printf("------------------\n"); } void game() { ········· } int main() { int input = 0; do { meau(); scanf("%d", &input); switch (input) { case 1 : game(); break; case 0 : break; default : printf("輸入錯(cuò)誤\n"); } } while (input); return 0; }
2.當(dāng)我們進(jìn)入case 1,運(yùn)行g(shù)ame()函數(shù);首先我們需要一個(gè)容器來存放我們的游戲數(shù)據(jù),此時(shí)創(chuàng)建字符二維數(shù)組arr[3][3]作為容器,玩家下的棋用“*”表示電腦用”#“表示。因?yàn)樾泻土卸紴?,后面經(jīng)常要使用,我們對(duì)他進(jìn)行宏定義一下
#define ROW 3 #define COL 3
dis_play( )函數(shù)
》.dis_play( ):我們下棋肯定需要棋盤來顯示我們的數(shù)據(jù),我們通過構(gòu)造一個(gè)函數(shù)dis_play()將數(shù)組打印出來來實(shí)現(xiàn)這一功能
dis_play()的功能其實(shí)就是把a(bǔ)rr[ROW][COL]以棋盤形式打印顯示出來,需要借助一些特殊字符”|“和”_“輔助打印
#define ROW 3 / 行:3 #define COL 3 / 列:3 void dis_play(char arr[ROW][COL]) { for (int i=0;i<ROW;i++) /for每一次進(jìn)去,打印一行數(shù)組和一條分割線 { for (int j = 0; j < COL; j++)//打印數(shù)組 { printf(" %c ", arr[i][j]); if (j < COL - 1) { printf("|"); } } printf("\n"); for (int k = 0; k < COL; k++)//打印分割線 { printf("---"); if (k < COL - 1) { printf("|"); } } printf("\n"); } }
初步運(yùn)行代碼,打印棋盤:
reset ( )函數(shù)
》reset ( ) :我們下完一盤棋,還想下該怎么辦?這時(shí)候我們構(gòu)造一個(gè)函數(shù)reset(),將棋盤數(shù)組的每一個(gè)元素重置為空格
reset()函數(shù),遍歷數(shù)組,賦值為空格
void reset( char arr[ROW][COL]) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { arr[i][j] = ' ';//賦值空格 } } }
player_move( )函數(shù)
》player_move( ):玩家下棋,不能隨便下,下過的地方不能下,我們構(gòu)造一個(gè)player_move()函數(shù)完成這一功能
player_move( )函數(shù)功能其實(shí)就是為數(shù)組arr[ROW][COL]賦值,數(shù)組元素為空格的地方就是可以下棋的地方
輸入坐標(biāo)時(shí),和我們程序員思維不同,正常人認(rèn)為行是從1開始而不是從0開始,玩家輸入的數(shù)據(jù)需要減1才能正常賦值
void player_move(char arr[ROW][COL]) { int row = 0, col = 0; while (1) { printf("玩家下棋,請(qǐng)輸入坐標(biāo)>:"); scanf("%d %d", &row, &col); if (arr[row-1][col-1] == ' ') { arr[row-1][col-1] = '*'; break; } printf("輸入錯(cuò)誤,請(qǐng)?jiān)俅屋斎隲n"); } }
玩家下棋
computer_move()函數(shù)
》computre_move()電腦下棋,為了更容易實(shí)現(xiàn)我們這里讓他再棋盤上隨機(jī)下,需要生成隨機(jī)數(shù)的知識(shí),我們需要構(gòu)造一個(gè)函數(shù)
使用頭文件#include<stdlib.h>中的rand()函數(shù)可以生成一個(gè)0~32767的偽隨機(jī)數(shù),但使用rand()前先要使用srand()設(shè)置偽隨機(jī)數(shù)起點(diǎn)
起點(diǎn)只要寫一次,我們將srand((unsigned)time(NULL))定義在主函數(shù),此處是一種固定的寫法,time()函數(shù)需要引<time.h>頭文件將rand()%3即%ROW可以生產(chǎn)0、1、2這三個(gè)隨機(jī)數(shù),可以用來做數(shù)組的行號(hào)和列標(biāo)
int main() { srand((unsigned)time(NULL));/設(shè)置起點(diǎn)的固定寫法 int input = 0; do { meau(); scanf("%d", &input); switch (input) { case 1 : game(); break; case 0 : break; default : printf("輸入錯(cuò)誤\n"); } } while (input); return 0; } void computer_move(char arr[ROW][COL]) { int row = rand() % ROW ;//利用隨機(jī)數(shù)生成行號(hào)列標(biāo) int col = rand() % COL ; printf("電腦下棋:>\n"); while (1) { if (arr[row][col] == ' ')//判斷是否為空格 { arr[row][col] = '#'; break; } row = rand() % ROW; col = rand() % COL; } }
電腦下棋
is_win()函數(shù)
》is_win()光下棋也不行,每當(dāng)玩家或電腦下一步棋必須有東西來判斷到底是玩家贏了還是電腦贏了還是平局還是繼續(xù),我們構(gòu)造is_win()函數(shù)完成這一功能
is_win()函數(shù)功能最后是返回一個(gè)字符,電腦贏返回"#",玩家贏返回”*“,平局返回”q“,以上情況都不符合就返回”c“(continue)
三子棋勝利無非就三種情況:行相同、列相同和對(duì)角線相同我們用for和if語(yǔ)句就可以判斷
平局的情況其實(shí)就是棋盤滿了,我們構(gòu)造一個(gè)is_fuii()函數(shù),棋盤滿了,該函數(shù)返回1否則返回0;
int is_full(char arr[ROW][COL]) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (arr[i][j] == ' ')/棋盤還有空格則return 0 return 0; } } return 1; } char is_win(char arr[ROW][COL]) /is_win()函數(shù) { for (int i = 0; i < ROW; i++)/判斷是否有行相同 { if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ') return arr[i][0]; } for (int i = 0; i <COL; i++)/判斷是否有列相同 { if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ') return arr[0][i]; } /判斷對(duì)角線是否相同 if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ') return arr[0][0]; if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[0][2] != ' ') return arr[0][2]; if (1==is_full(arr))/is_full()返回1則return ‘q' { return 'q'; } return 'c';/都不滿足,return ‘c' }
總結(jié)
到此這篇關(guān)于200行C語(yǔ)言代碼實(shí)現(xiàn)簡(jiǎn)易三子棋游戲的文章就介紹到這了,更多相關(guān)C語(yǔ)言三子棋游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c語(yǔ)言生成隨機(jī)數(shù)的方法(獲得一組不同的隨機(jī)數(shù))
c語(yǔ)言生成一組不同的隨機(jī)數(shù),大家參考使用吧2013-12-12C語(yǔ)言中浮點(diǎn)數(shù)的精度丟失問題解決
大家好,本篇文章主要講的是C語(yǔ)言中浮點(diǎn)數(shù)的精度丟失問題解決,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01Qt實(shí)現(xiàn)制作簡(jiǎn)單的計(jì)算器
計(jì)算器是我們生活中很常見的東西,它可以由多種語(yǔ)言多種方式來實(shí)現(xiàn)。本文主要介紹的是利用Qt實(shí)現(xiàn)的簡(jiǎn)易計(jì)算器的制作,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-12-12適合初學(xué)者的C語(yǔ)言數(shù)據(jù)類型的講解
在 C 語(yǔ)言中,數(shù)據(jù)類型指的是用于聲明不同類型的變量或函數(shù)的一個(gè)廣泛的系統(tǒng)。變量的類型決定了變量存儲(chǔ)占用的空間,以及如何解釋存儲(chǔ)的位模式。2022-04-04C語(yǔ)言return, exit, abort的區(qū)別
這篇文章主要介紹了C語(yǔ)言return, exit, abort的區(qū)別,一般情況下,在C語(yǔ)言中退出一個(gè)程序用return,如果在main函數(shù)中,return在清理局部對(duì)象之后,會(huì)調(diào)用exit函數(shù),和return相比,exit并不會(huì)銷毀局部對(duì)象,下面一起進(jìn)入文章了解更詳細(xì)內(nèi)容吧,需要的朋友也可以參考一下2022-01-01C++?Boost?CircularBuffer算法超詳細(xì)精講
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱2022-11-11