C語言三子棋游戲的簡單設計
本文實例為大家分享了C語言三子棋游戲簡單設計的具體代碼,供大家參考,具體內容如下
題目思想:
用 3×3 的二維數組表示棋盤
每一個棋子的格子,也就是每個元素表示三種狀態(tài):分別是
1.未落子 ‘ '
2.玩家落子 ‘X'
3.電腦落子 ‘O'
玩家通過輸入數字作為落子位置的坐標(輸入的行數與輸入的列數)
直接上代碼解析
1.創(chuàng)建出棋盤
#define _CRT_SECURE_NO_WARNINGS
//利用宏定義行和列
#define MAX_ROW 3
#define MAX_COL 3
#include <stdio.h>
#include <stdlib.h>
// 將初始化行和列的 '0' 變?yōu)榭崭?' '
void init(char board[MAX_ROW][MAX_COL]) {
//行初始化,將數組 0-2輸出為' '
for(int row = 0; row < MAX_ROW; row++) {
//列初始化
for (int col = 0; col < MAX_COL; col++) {
board[row][col] = ' ';
}
}
}
// 打印棋盤,定義printBoard,以二維數組的方式進行循環(huán)打印
void printBoard(char board[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
// 打印字符,使用 %c
printf("%c", board[row][col]);
}
//每次打印完一行,進行換行操作,變成3×3的數組形成的棋盤
printf("\n");
}
}
int main() {
// 首先創(chuàng)建棋盤并初始化
// 這里不要用board[3][3],防止后面 3 與 3 搞混,可以利用宏定義
char board[MAX_ROW][MAX_COL] = { 0 };
// 使用 init 函數 初始化二維數組{0}應當變成空格 ' '
// 此處也可以將 init函數定義中的雙重 for 循環(huán)直接輸入
// 但將二維數組初始化為 ' ',表示了一個固定功能的邏輯,比較適合用函數定義的方法完成
init(board);
// 使用while循環(huán),進行輪流落子
while (1) {
//1.先打印棋盤內容
printBoard(board);
//2.玩家落子
//3.電腦落子
//4.判定勝負
}
system("pause");
return 0;
}

確實打印出來了,但是由于初始化將二維數組中的元素變?yōu)榱丝崭?‘ '
,所以輸出結果看不到。
2.修改棋盤,使之打印出的是 3×3 的帶有方格的棋盤
void printBoard(char board[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) {
//在打印每一行之前加入橫線
printf("+--+--+--+\n");
for (int col = 0; col < MAX_COL; col++) {
// 打印字符,使用 %c
// 每打印一列,在打印之前加入|
printf("| %c", board[row][col]);
}
//打印之后加入|,形成 3 列。
printf("|");
//每次打印完一行,進行換行操作,變成3×3的數組形成的縱線棋盤
printf("\n");
}//打印完所有行之后在加入橫線,形成橫線棋盤
printf("+--+--+--+\n");
}

3.玩家落子
// 玩家落子
void playerMove(char board[MAX_ROW][MAX_COL]) {
printf("輪到玩家落子!\n");
//加入while循環(huán),保證用戶輸入錯誤時返回重新輸入
while (1) {
printf("請輸入落子位置的坐標(row col):");
//添加屏幕輸入模塊,輸入行和列坐標
int row = 0;
int col = 0;
scanf("%d %d", &row, &col);
//輸入完了之后,一定要驗證輸入的內容,防止輸入例如(10,20)超過棋盤坐標
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
printf("您輸入的坐標有誤,請重新輸入!\n");
continue;//重新輸入,繼續(xù)循環(huán)
}
// 當前位置不為 ' ' ,說明有子了,也需要重新輸入
if (board[row][col] != ' ') {
printf("當前位置有子,無法落子\n");
continue;
}
//玩家落子為 X ,結束當前循環(huán)
board[row][col] = 'X';
break;
}
}

4.電腦落子
// 電腦落子
void computerMove(char board[MAX_ROW][MAX_COL]) {
printf("輪到電腦落子!\n");
while (1) {
//電腦落子時,產生隨機位置,用到隨機數種子,使隨機數范圍在棋盤坐標以內
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (board[row][col] != ' '){
// 如果行列不是空格,說明有子了,就隨機生成隨機數
continue;
}
board[row][col] = 'O';
break;
}
}

這里使用了清屏操作,讓每次輸入完后進行一次清屏,具體代碼在總體代碼里附上
5.判定勝負
//判斷和棋的函數
int isFull(char board[MAX_ROW][MAX_COL]) {
//如果在棋盤中找不到 ' ' ,就說明棋盤滿了,只要找到 ' ' 說明沒滿
//約定滿了返回1,沒滿返回0
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
if (board[row][col] == ' ') {
//沒滿
return 0;
}
}
}return 1;
}
// 判定勝負,由于要返回勝負,使用char定義
// 如果是玩家贏返回 X ,電腦贏返回 O,平局返回 P,勝負未分返回 ' '
char checkwinner(char board[MAX_ROW][MAX_COL]) {
//1.檢測所有行
for (int row = 0; row < MAX_ROW; row++) {
if (board[row][0] != ' ' &&
board[row][0] == board[row][1]
&& board[row][0] == board[row][2]) {
return board[row][0];
}
}
//2.檢測所有列
for (int col = 0; col < MAX_ROW; col++) {
if (board[0][col] != ' ' &&
board[0][col] == board[1][col]
&& board[0][col] == board[2][col]) {
return board[0][col];
}
}
//3.檢測所有對角線
if (board[0][0] != ' ' &&
board[0][0] == board[1][1]
&& board[0][0] == board[2][2]) {
return board[0][0];
}
if (board[2][0] != ' ' &&
board[2][0] == board[1][1]
&& board[0][0] == board[0][2]) {
return board[2][0];
}
// 判定和棋
if (isFull(board)) {
return 'p';
}return ' ';
}

這個結果中很多人肯定看到了問題,玩家贏的同時還在顯示電腦落子,怎么改?
6.注意還有一個問題:

如圖,在主函數中先進行玩家落子,后進行電腦落子,在電腦落子之前玩家就贏了。修改程序如下:
int main() {
// 首先創(chuàng)建棋盤并初始化
// 這里不要用board[3][3],防止后面 3 與 3 搞混,可以利用宏定義
char board[MAX_ROW][MAX_COL] = { 0 };
// 使用 init 函數 初始化二維數組{0}應當變成空格 ' '
// 此處也可以將 init函數定義中的雙重 for 循環(huán)直接輸入
// 但將二維數組初始化為 ' ',表示了一個固定功能的邏輯,比較適合用函數定義的方法完成
init(board);
char winner = ' ';
// 使用while循環(huán),進行輪流落子
while (1) {
//1.先打印棋盤內容
printBoard(board);
//2.玩家落子
playerMove(board);
winner = checkwinner(board);
if (winner != ' ') {
//勝負已分,結束循環(huán)
break;
}
//3.電腦落子
computerMove(board);
//4.判定勝負
winner = checkwinner(board);
if (winner != ' ') {
//勝負已分,結束循環(huán)
break;
}
}
if (winner = 'X') {
printf("恭喜你,獲勝了!\n");
}
else if (winner = 'O') {
printf("很遺憾,你有點菜呀!\n");
}
else {
printf("你和電腦五五開!\n");
}
system("pause");
return 0;
}
全部函數
#define _CRT_SECURE_NO_WARNINGS
//利用宏定義行和列
#define MAX_ROW 3
#define MAX_COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 將初始化行和列的 '0' 變?yōu)榭崭?' '
void init(char board[MAX_ROW][MAX_COL]) {
//行初始化,將數組 0-2輸出為' '
for(int row = 0; row < MAX_ROW; row++) {
//列初始化
for (int col = 0; col < MAX_COL; col++) {
board[row][col] = ' ';
}
}
//設置隨機數種子,為電腦落子
//只要程序啟動時,設置一次即可
srand((unsigned int)time(0));
}
// 打印棋盤,定義printBoard,以二維數組的方式進行循環(huán)打印
void printBoard(char board[MAX_ROW][MAX_COL]) {
//每次打印之前先清屏
system("cls");
for (int row = 0; row < MAX_ROW; row++) {
//在打印每一行之前加入橫線
printf("+--+--+--+\n");
for (int col = 0; col < MAX_COL; col++) {
// 打印字符,使用 %c
// 每打印一列,在打印之前加入|
printf("| %c", board[row][col]);
}
//打印之后加入|,形成 3 列。
printf("|");
//每次打印完一行,進行換行操作,變成3×3的數組形成的縱線棋盤
printf("\n");
}//打印完所有行之后在加入橫線,形成橫線棋盤
printf("+--+--+--+\n");
}
// 玩家落子
void playerMove(char board[MAX_ROW][MAX_COL]) {
printf("輪到玩家落子!\n");
//加入while循環(huán),保證用戶輸入錯誤時返回重新輸入
while (1) {
printf("請輸入落子位置的坐標(row col):");
//添加屏幕輸入模塊,輸入行和列坐標
int row = 0;
int col = 0;
scanf("%d %d", &row, &col);
//輸入完了之后,一定要驗證輸入的內容,防止輸入例如(10,20)超過棋盤坐標
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
printf("您輸入的坐標有誤,請重新輸入!\n");
continue;//重新輸入,繼續(xù)循環(huán)
}
// 當前位置不為 ' ' ,說明有子了,也需要重新輸入
if (board[row][col] != ' ') {
printf("當前位置有子,無法落子\n");
continue;
}
//玩家落子為 X ,結束當前循環(huán)
board[row][col] = 'X';
break;
}
}
// 電腦落子
void computerMove(char board[MAX_ROW][MAX_COL]) {
printf("輪到電腦落子!\n");
while (1) {
//電腦落子時,產生隨機位置,用到隨機數種子,使隨機數范圍在棋盤坐標以內
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (board[row][col] != ' '){
// 如果行列不是空格,說明有子了,就隨機生成隨機數
continue;
}
board[row][col] = 'O';
break;
}
}
//判斷和棋的函數
int isFull(char board[MAX_ROW][MAX_COL]) {
//如果在棋盤中找不到 ' ' ,就說明棋盤滿了,只要找到 ' ' 說明沒滿
//約定滿了返回1,沒滿返回0
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
if (board[row][col] == ' ') {
//沒滿
return 0;
}
}
}return 1;
}
// 判定勝負,由于要返回勝負,使用char定義
// 如果是玩家贏返回 X ,電腦贏返回 O,平局返回 P,勝負未分返回 ' '
char checkwinner(char board[MAX_ROW][MAX_COL]) {
//1.檢測所有行
for (int row = 0; row < MAX_ROW; row++) {
if (board[row][0] != ' '
&& board[row][0] == board[row][1]
&& board[row][0] == board[row][2]) {
return board[row][0];
}
}
//2.檢測所有列
for (int col = 0; col < MAX_ROW; col++) {
if (board[0][col] != ' '
&& board[0][col] == board[1][col]
&& board[0][col] == board[2][col]) {
return board[0][col];
}
}
//3.檢測所有對角線
if (board[0][0] != ' ' &&
board[0][0] == board[1][1]
&& board[0][0] == board[2][2]) {
return board[0][0];
}
if (board[2][0] != ' ' &&
board[2][0] == board[1][1]
&& board[0][0] == board[0][2]) {
return board[2][0];
}
// 判定和棋
if (isFull(board)) {
return 'p';
}return ' ';
}
int main() {
// 首先創(chuàng)建棋盤并初始化
// 這里不要用board[3][3],防止后面 3 與 3 搞混,可以利用宏定義
char board[MAX_ROW][MAX_COL] = { 0 };
// 使用 init 函數 初始化二維數組{0}應當變成空格 ' '
// 此處也可以將 init函數定義中的雙重 for 循環(huán)直接輸入
// 但將二維數組初始化為 ' ',表示了一個固定功能的邏輯,比較適合用函數定義的方法完成
init(board);
char winner = ' ';
// 使用while循環(huán),進行輪流落子
while (1) {
//1.先打印棋盤內容
printBoard(board);
//2.玩家落子
playerMove(board);
winner = checkwinner(board);
if (winner != ' ') {
//勝負已分,結束循環(huán)
break;
}
//3.電腦落子
computerMove(board);
//4.判定勝負
winner = checkwinner(board);
if (winner != ' ') {
//勝負已分,結束循環(huán)
break;
}
}
if (winner = 'X') {
printf("恭喜你,獲勝了!\n");
}
else if (winner = 'O') {
printf("很遺憾,你有點菜呀!\n");
}
else {
printf("你和電腦五五開!\n");
}
system("pause");
return 0;
}
結果如下

我們的三子棋棋盤小游戲就算結束啦!
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
詳解C++中賦值,關系,函數調用運算符重載的實現(xiàn)
本文主要為大家講解一下三個C++中的運算符重載,分別是賦值運算符重載、關系運算符重載和函數調用運算符重載,感興趣的小伙伴可以跟隨小編一起學習一下2022-06-06
C語言創(chuàng)建鏈表錯誤之通過指針參數申請動態(tài)內存實例分析
這篇文章主要介紹了C語言創(chuàng)建鏈表錯誤之通過指針參數申請動態(tài)內存,是鏈表創(chuàng)建過程中非常常見的經典錯誤。實例中做了較為詳盡的分析,需要的朋友可以參考下2014-09-09

