今天,我們來再來實作一個大家都不陌生的小專案:三子棋,

1,三子棋
1,思路分析
寫一個小專案,必不可少的是思路的構建,寫一個游戲,我們首先需要一個選單,這是最基本的,讓用戶來選擇是否要玩這個游戲,如果要玩,就進入游戲主體的部分,不玩就直接退出,最簡單的思路就是這樣,而后一些細節的實作,比如游戲主體的實作需要在程序中配合去講,
這里,我們將用到自己創建的頭檔案,以及多個.c檔案,主要為了避免主函式中過于繁雜,龐大,我們將大部分功能封裝成函式來實作,
2,代碼實操
game.h檔案中
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define ROW 3
#define COL 3
void Initialboard(char board[ROW][COL], int row, int col);
void Displayboard(char board[ROW][COL], int row, int col);
void playeremove(char board[ROW][COL], int row, int col);
void computermove(char board[ROW][COL],int row,int col);
char Iswin(char board[ROW][COL], int row, int col);
char Isfull(char board[ROW][COL], int row, int col);
這里可以看到,我們將一些函式都放到這里宣告,包括需要用到的一些庫函式的頭檔案,這樣,我們在.c檔案中就只需要包含我們自己寫的頭檔案就可以,簡化程式,當然,不要忘記參考自己寫的頭檔案需要使用雙引號""
game.c檔案
#include"game.h"
//初始化棋盤
void Initialboard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//列印棋盤
// | |
//---|---|—-
// | |
//---|—-|---
// | |
void Displayboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (i == 0)
{
for (j = 0; j < col; j++)
{
if (j == 0)
printf(" %d ",j);
else
printf(" %d ", j);
}
printf("\n");
}
printf("%d",i);
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < (col - 1))
{
printf("|");
}
}
printf("\n");
if (i<row - 1)
{
for (j = 0; j < col; j++)
{
if (j==0)
printf(" ---");
else
printf("---");
if (j < (col - 1))
printf("|");
}
}
printf("\n");
}
}
//實作玩家下棋
void playermove(char board[ROW][COL], int row, int col)
{
int i, j;
printf("請根據圖示輸入要走的坐標:");
while (1)
{
scanf("%d%d",&i,&j);
if (i >= 0 && i < 3 && j >= 0 && j <3 && board[i][j] == ' ')
{
board[i][j] = '*';
break;
}
else
printf("輸入有誤,請重新輸入,");
}
}
void computermove(char board[ROW][COL], int row, int col)
{
while (1)
{
int i = rand() % row;
int j = rand() % col;
if (board[i][j] == ' ')
{
board[i][j] = '#';
break;
}
}
}
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
{
return board[i][j];
}
}
}
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 2; i++)
{
if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
{
return board[i][j];
}
}
}
for (i = 0, j = 0; i < row - 2 && j < col - 2; i++, j++)
{
if (board[i][j] == board[i + 1][j+1] && board[i + 1][j+1] == board[i + 2][j+2] && board[i][j] != ' ')
{
return board[i][j];
}
}
for (i = row-1, j = 0; i >=0 && j < col-2; i--, j++)
{
if (board[i][j] == board[i -1][j + 1] && board[i - 1][j + 1] == board[i -2][j + 2] && board[i][j] != ' ')
{
return board[i][j];
}
}
return 'c';
}
char Isfull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col;j++)
{
if (board[i][j] == ' ')
return 'c';
}
}
return 'e';
}
三子棋.c檔案
#include"game.h"
//說明:
//*是玩家走的棋子
//#是電腦走的棋子
void menu()
{
printf("*****************\n");
printf("**1,play 0,exit**\n");
printf("*****************\n");
printf("請選擇:");
}
void game()
{
char win = 'c';
char board[ROW][COL] = { 0};//創建棋盤
Initialboard(board, ROW, COL);//初始化棋盤
Displayboard(board, ROW, COL);//列印出棋盤的資訊
while (1)
{
//玩家走
printf("玩家走\n");
playermove(board, ROW, COL);
Displayboard(board, ROW, COL);
win = Isfull(board, ROW, COL);
win=Iswin(board,ROW,COL);
if (win != 'c')
break;
//電腦走
printf("電腦走\n");
computermove(board, ROW, COL);
Displayboard(board, ROW, COL);
win = Isfull(board, ROW, COL);
win=Iswin(board,ROW,COL);
if (win != 'c')
break;
}
if (win == 'e')
printf("平局\n");
else if (win == '*')
printf("玩家贏\n");
else if (win == '#')
printf("電腦贏\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
//選單,讓用戶選擇
menu();
scanf("%d", &input);
if (input != 0)
{
printf("游戲開始\n");
game();//游戲主體
}
else
{
printf("退出游戲\n");
break;
}
} while (input);
return 0;
}
3,最后解釋
這里將兩個合起來一起說,首先,在三子棋.c檔案中,我們實作了上面的基本思路,而進入游戲主體部分之后,我們需要的是創建一個棋盤來存放我們的資訊,之后,初始化棋盤,列印棋盤,這里,我們使用了宏定義,直接定義ROW,COL,行和列,方便我們之后進行修改,來改變棋盤的大小,而后,就是進行三子棋的玩家和電腦的走法了,玩家走比較簡單,我們在列印棋盤的時候就已經讓棋盤上有標坐標了,玩家只需要根據坐標來選,在將資訊存入就可以了,而電腦的走法就需要我們之前使用過的rand函式了,還記得嗎,不記得的話大家可以回去看看
小專案的實作:猜數字小游戲+亂數生成器的實作_C_Ryson的博客-CSDN博客
用取模的方式限制住亂數的范圍,我們就可以放入棋盤了,有了這兩個之后,最重要的就是判斷規則了,大家有興趣的話,可以去看看??????C語言從入門到進階(C語言入門搞定C語言C語言視頻教程C語言入門到進階C語言教程C語言教程C語言教程C語言入門教程C語言入教程C語言C語言視頻C語言教程)_嗶哩嗶哩_bilibili
這里的規則是我自己寫的,原本是想讓其普適高一些,放大棋盤之后還能使用,結果發現,三子棋放大棋盤之后,先手的一定會贏,這讓我之后想寫的雙人對戰的夢想破滅了,于是,我就將其用到了五子棋(進階版),這里礙于時間原因,就這兩天寫給大家吧,這里只寫一下五子棋的普通版本有興趣的話記得點個關注,明天來看哦,
在判斷規則中,我們利用放進去陣列元素的特點,直接回傳就行,利用陣列的元素來判斷是否本局已經結束,而一開始,我們用變數win儲存的字母c(continue)來表示游戲繼續,如果win的值被改變,就證明游戲已經結束,可以跳出回圈了,再進行判斷的,同時,我們要注意到,因為棋盤的大小被我們所限定,還有可能出現一個問題是平局,也就是棋盤滿的情況,所以我們還需要一個Isfull函式來判斷一下,一旦棋盤上所有的元素都不在有空格,又還沒分出勝負,那么就是平局了,這樣,一個完整的判斷規則就寫完了,
接下來重點說一下我自己寫的上面的規則,
我們知道三子棋要贏只需要有三個棋子在一條直線上,那么這時候,我們就可以創建兩個變數,使其都在行和列范圍內,并然后嵌套回圈i,j,改變來判斷豎列的,和橫列的,再將i,j,同時改變,來判斷斜著的直線,
這時候,不管棋盤變得多么大,判斷規則依然成立,
之后的收尾,就是像上次猜數字游戲一樣讓用戶選擇是否繼續玩就可以了,
2,五子棋(初階版)
重頭戲五子棋來啦,

1,思路分析
其實,五子棋的整體思路和三子棋差不多,整體構建的代碼也類似,只是將判斷規則放大,將棋盤放大而已,我們邊看代碼邊說吧,
2,代碼實作
首先,依然是自己的頭檔案,
game.h檔案
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define ROW 5
#define COL 5
void Initialboard(char board[ROW][COL], int row, int col);
void Displayboard(char board[ROW][COL], int row, int col);
void playeremove(char board[ROW][COL], int row, int col);
void computermove(char board[ROW][COL], int row, int col);
char Iswin(char board[ROW][COL], int row, int col);
char Isfull(char board[ROW][COL], int row, int col);
簡化代碼的運用,這里我們將ROW和COL定義成了5,當然,也可以自己定得更大,不過,跟電腦對戰(還沒升級的),太大的棋盤反而沒什么用處,雖然升級也不算太好,畢竟本人才疏學淺,主要升級的思路只在于,讓電腦在玩家下的棋的周圍下,之后學得更多,在來進行優化吧,這里這個簡陋的升級就不展示啦,
game.c檔案
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//初始化棋盤
void Initialboard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//列印棋盤
// | |
//---|---|—-
// | |
//---|—-|---
// | |
void Displayboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (i == 0)
{
for (j = 0; j < col; j++)
{
if (j == 0)
printf(" %d ", j);
else
printf(" %d ", j);
}
printf("\n");
}
printf("%d", i);
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < (col - 1))
{
printf("|");
}
}
printf("\n");
if (i<row - 1)
{
for (j = 0; j < col; j++)
{
if (j == 0)
printf(" ---");
else
printf("---");
if (j < (col - 1))
printf("|");
}
}
printf("\n");
}
}
//實作玩家下棋
void playermove(char board[ROW][COL], int row, int col)
{
int i, j;
printf("請根據圖示輸入要走的坐標:");
while (1)
{
scanf("%d%d", &i, &j);
if (i >= 0 && i < 5 && j >= 0 && j <5 && board[i][j] == ' ')
{
board[i][j] = '*';
break;
}
else
printf("輸入有誤,請重新輸入,");
}
}
void computermove(char board[ROW][COL], int row, int col)
{
while (1)
{
int i = rand() % row;
int j = rand() % col;
if (board[i][j] == ' ')
{
board[i][j] = '#';
break;
}
}
}
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 4; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] &&board[i][j+2]==board[i][j+3]&&board[i][j+3]==board[i][j+4]&& board[i][j] != ' ')
{
return board[i][j];
}
}
}
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 4; i++)
{
if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')
{
return board[i][j];
}
}
}
for (i = 0, j = 0; i < row - 4 && j < col - 4; i++, j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4]&& board[i][j] != ' ')
{
return board[i][j];
}
}
for (i = row - 1, j = 0; i >= 0 && j < col - 4; i--, j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4]&& board[i][j] != ' ')
{
return board[i][j];
}
}
return 'c';
}
char Isfull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 'c';
}
}
return 'e';
}
五子棋(初階).c檔案
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//說明:
//*是玩家走的棋子
//#是電腦走的棋子
void menu()
{
printf("*****************\n");
printf("**1,play 0,exit**\n");
printf("*****************\n");
printf("請選擇:");
}
void game()
{
char win = 'c';
char board[ROW][COL] = { 0 };//創建棋盤
Initialboard(board, ROW, COL);//初始化棋盤
Displayboard(board, ROW, COL);//列印出棋盤的資訊
while (1)
{
//玩家走
printf("玩家走\n");
playermove(board, ROW, COL);
Displayboard(board, ROW, COL);
win = Isfull(board, ROW, COL);
win = Iswin(board, ROW, COL);
if (win != 'c')
break;
//電腦走
printf("電腦走\n");
computermove(board, ROW, COL);
Displayboard(board, ROW, COL);
win = Isfull(board, ROW, COL);
win = Iswin(board, ROW, COL);
if (win != 'c')
break;
}
if (win == 'e')
printf("平局\n");
else if (win == '*')
printf("玩家贏\n");
else if (win == '#')
printf("電腦贏\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
//選單,讓用戶選擇
menu();
scanf("%d", &input);
if (input != 0)
{
printf("游戲開始\n");
game();//游戲主體
}
else
{
printf("退出游戲\n");
break;
}
} while (input);
return 0;
}
3,最后解讀
這里,我們再次合起來說吧,大家也可以看到,實際上和三子棋的實作沒有多大的區別,主要的改變,都在規則部分,我們拿出來細說,
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 4; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] &&board[i][j+2]==board[i][j+3]&&board[i][j+3]==board[i][j+4]&& board[i][j] != ' ')
{
return board[i][j];
}
}
}
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 4; i++)
{
if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')
{
return board[i][j];
}
}
}
for (i = 0, j = 0; i < row - 4 && j < col - 4; i++, j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4]&& board[i][j] != ' ')
{
return board[i][j];
}
}
for (i = row - 1, j = 0; i >= 0 && j < col - 4; i--, j++)
{
if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4]&& board[i][j] != ' ')
{
return board[i][j];
}
}
return 'c';
}
可以看到,我們將規則又擴大了一些,從原本的三個擴大到了5個位置的相等,而之后同樣也是回傳陣列里的元素,來幫助判斷勝負,同時要注意不要越界訪問了,
這就是今天的內容了,之后五子棋的進階部分找時間再分享給大家,進階部分更加精彩,有我自己搗鼓的一個簡陋的登錄系統(只是一個雛形,不能儲存資料),以及玩家對戰部分等,碼字不易,大家點點關注,給我點個贊吧,我會堅持更新的,如果有錯,請聯系修改,你們的支持是我更新的動力,
參考資料:
五子棋圖片 - 國內版 Bing images
三子棋圖片 - 國內版 Bing images
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/336325.html
標籤:其他
