C語言實作三子棋游戲
- 代碼下載
- 一、多檔案思維
- 二、游戲總體思路與函式設計實作
- 2.1 游戲選單Menu
- 2.2 顯示棋盤ShowBoard
- 2.3 玩家移動PlayerMove
- 2.4 判斷輸贏Judge
- 2.5 電腦移動ComputerMove
- 2.5 游戲主控制函式Game
- 三、多檔案代碼清單
- 3.1 game.h
- 3.2 game.c
- 3.3 main.c
代碼下載
Github原始碼下載地址:
https://github.com/Kyrie-leon/C_Project/tree/master/Three_Game
一、多檔案思維
我們使用多檔案實作三子棋游戲,培養多檔案思維,分別為game.h、game.c和main.c
二、游戲總體思路與函式設計實作
三子棋游戲的主要思路為:
玩家通過選單進入游戲->顯示棋盤->玩家移動->判斷輸贏->電腦移動->判斷輸贏
上述函式封裝在game.c檔案中
2.1 游戲選單Menu
void Menu()
{
printf("################################\n");
printf("#### 1.Play 2.Exit ####\n");
printf("################################\n");
printf("Please input your selection#: ");
}
2.2 顯示棋盤ShowBoard
棋盤用一個二維陣列來存盤并顯示,對于沒有下過棋子的位置統一用’空格存盤,由于電腦的解析度不同,棋盤的形狀需要不斷除錯,
void ShowBoard(char board[][COL],int row, int col)
{
printf(" | 1 | 2 | 3 |\n");
printf("----------------\n");
//外層回圈控制每一行,內層回圈控制每一列
for (int i = 0; i < ROW; i++)
{
printf(" %d | ",i+1);
for (int j = 0; j < COL; j++)
{
printf("%c | ", board[i][j]);
}
printf("\n----------------\n");
}
}
2.3 玩家移動PlayerMove
玩家棋子用X表示,在輸入位置后需要判斷落子的地方是否合法,主要為如下情況
1.越界,即超出棋盤范圍,
2. 落子位置被占用,即該位置已經存在玩家棋子或者電腦棋子
void PlayerMove(char board[][COL], int row, int col)
{
//定義輸入坐標x,y
int x = 0;
int y = 0;
while (1)
{
printf("請輸入你的位置:");
scanf("%d %d", &x, &y);
if (x < 1 || x>3 || y < 1 || y>3)
{
printf("你輸入的坐標有誤!\n");
continue;
}
//需要注意用戶輸入的坐標從1開始,而程式定義的棋盤坐標從0開始
else if (board[x - 1][y - 1] != ' ')
{
printf("你輸入的位置已經被占用!\n");
continue;
}
else
{
board[x - 1][y - 1] = P_COLOR;
break;
}
}
}
2.4 判斷輸贏Judge
判斷輸贏的幾種情況已經在代碼中給出注釋,不懂的話可以評論問我
char Judge(char board[][COL], int row, int col)
{
//1.遍歷每一行是否三子成珠
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && \
board[i][1] == board[i][2] && \
board[i][0] != ' ')
{
return board[i][0];
}
}
//2.遍歷每一列是否三子成珠
for (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && \
board[1][j] == board[2][j] && \
board[0][j] != ' ')
{
return board[0][j];
}
}
//3.遍歷九宮格對角線是否三子成珠
if (board[0][0] == board[1][1] && \
board[1][1] == board[2][2] && \
board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && \
board[1][1] == board[2][0] && \
board[0][2] != ' ')
{
return board[0][2];
}
//4.沒有出現三子成珠,且棋盤還有空位,繼續下棋
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return NEXT;
}
}
}
//5.上述條件都不滿足,和棋
return DRAW;
}
2.5 電腦移動ComputerMove
電腦落子我們使用隨機落子,如果想要更加智能可以采取一些策略
void ComputerMove(char board[][COL], int row, int col)
{
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = C_COLOR;
break;
}
}
}
2.5 游戲主控制函式Game
void Game()
{
//定義一個隨機種子用于電腦落子
srand((unsigned long)time(NULL));
//定義棋盤
char board[ROW][COL];
//棋盤初始化為空
memset(board, ' ', sizeof(board));
//定義變數result用于判斷輸贏情況
char result='x';
do
{
ShowBoard(board, ROW, COL);
PlayerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出現三子成珠,跳出回圈,給出輸贏結果
if (result != NEXT)
{
break;
}
ComputerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出現三子成珠情況,跳出回圈,給出輸贏結果
if (result != NEXT)
{
break;
}
} while (1);
//列印輸贏結果
if (P_COLOR == result)
{
printf("你贏了!\n");
}
else if (C_COLOR == result)
{
printf("你輸了!\n");
}
else
{
printf("和棋!\n");
}
//此處再次呼叫顯示棋盤函式,用于顯示最終的落子情況,如果不呼叫該函式,會出現看不到最后一次落子的棋盤
ShowBoard(board, ROW, COL);
}
三、多檔案代碼清單
3.1 game.h
用于存放實作游戲的所有庫函式和函式宣告,以及一些宏定義方便后續更改
使用ifndef/define/endif防止頭檔案的重復包含和編譯,
#ifndef _GAME_H
#define _GAME_H
#include <stdio.h>
#include <Windows.h>
#include <time.h>
#pragma warning(disable:4996)
//定義棋盤大小
#define ROW 3
#define COL 3
//定義玩家與電腦棋子顏色
#define P_COLOR 'X'
#define C_COLOR 'O'
#define NEXT 'N'
#define DRAW 'D'
void Menu();
void Game();
#endif
3.2 game.c
用于存放實作游戲的所有函式定義
#include "game.h"
void Menu()
{
printf("################################\n");
printf("#### 1.Play 2.Exit ####\n");
printf("################################\n");
printf("Please input your selection#: ");
}
void ShowBoard(char board[][COL],int row, int col)
{
printf(" | 1 | 2 | 3 |\n");
printf("----------------\n");
//外層回圈控制每一行,內層回圈控制每一列
for (int i = 0; i < ROW; i++)
{
printf(" %d | ",i+1);
for (int j = 0; j < COL; j++)
{
printf("%c | ", board[i][j]);
}
printf("\n----------------\n");
}
}
void PlayerMove(char board[][COL], int row, int col)
{
//定義輸入坐標x,y
int x = 0;
int y = 0;
while (1)
{
printf("請輸入你的位置:");
scanf("%d %d", &x, &y);
if (x < 1 || x>3 || y < 1 || y>3)
{
printf("你輸入的坐標有誤!\n");
continue;
}
//需要注意用戶輸入的坐標從1開始,而程式定義的棋盤坐標從0開始
else if (board[x - 1][y - 1] != ' ')
{
printf("你輸入的位置已經被占用!\n");
continue;
}
else
{
board[x - 1][y - 1] = P_COLOR;
break;
}
}
}
char Judge(char board[][COL], int row, int col)
{
//1.遍歷每一行是否三子成珠
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && \
board[i][1] == board[i][2] && \
board[i][0] != ' ')
{
return board[i][0];
}
}
//2.遍歷每一列是否三子成珠
for (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && \
board[1][j] == board[2][j] && \
board[0][j] != ' ')
{
return board[0][j];
}
}
//3.遍歷九宮格對角線是否三子成珠
if (board[0][0] == board[1][1] && \
board[1][1] == board[2][2] && \
board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && \
board[1][1] == board[2][0] && \
board[0][2] != ' ')
{
return board[0][2];
}
//4.沒有出現三子成珠,且棋盤還有空位,繼續下棋
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return NEXT;
}
}
}
//5.上述條件都不滿足,和棋
return DRAW;
}
void ComputerMove(char board[][COL], int row, int col)
{
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = C_COLOR;
break;
}
}
}
void Game()
{
//定義一個隨機種子用于電腦落子
srand((unsigned long)time(NULL));
//定義棋盤
char board[ROW][COL];
//棋盤初始化為空
memset(board, ' ', sizeof(board));
//定義變數result用于判斷輸贏情況
char result='x';
do
{
ShowBoard(board, ROW, COL);
PlayerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出現三子成珠,跳出回圈,給出輸贏結果
if (result != NEXT)
{
break;
}
ComputerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出現三子成珠情況,跳出回圈,給出輸贏結果
if (result != NEXT)
{
break;
}
} while (1);
//列印輸贏結果
if (P_COLOR == result)
{
printf("你贏了!\n");
}
else if (C_COLOR == result)
{
printf("你輸了!\n");
}
else
{
printf("和棋!\n");
}
//此處再次呼叫顯示棋盤函式,用于顯示最終的落子情況,如果不呼叫該函式,會出現看不到最后一次落子的棋盤
ShowBoard(board, ROW, COL);
}
3.3 main.c
實作三子棋游戲的主選單和實作步驟
#include "game.h"
int main()
{
int select=0;
int quit = 0;
while(!quit)
{
Menu();
scanf("%d", &select);
switch(select)
{
case 1:
Game();
break;
case 2:
quit = 1;
break;
default:
printf("Please input again\n");
break;
}
}
printf("ByeBye!\n");
system("pause");
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/200805.html
標籤:其他
上一篇:JZOJ 6838. 【2020.10.31提高組模擬】小j的組合(樹的直徑)
下一篇:天梯賽訓練賽(一)
