目錄
一、游戲簡介
二、游戲設計
2.1 棋盤設計
2.2 模型設計
三、游戲實作
3.1 SanZiQiMain.c
3.1.1 main(主模塊)
3.1.2 choiceMenu(開始選單)
3.2 Game.c
3.2.1 game(游戲執行)
3.2.2 boardInit(初始化陣列)
3.2.3 displayBoard(顯示棋盤)
3.2.4 playerMove(玩家下棋)
3.2.5 computerMove(電腦下棋)
3.2.6 isWin(判斷贏棋)
四、游戲測驗
五、游戲代碼
3.1 Main.c
3.2 Game.c
3.3 Game.h
一、游戲簡介
三子棋是黑白棋的一種,三子棋是一種民間傳統游戲,又叫九宮棋、圈圈叉叉、一條龍、井字棋等,將正方形對角線連起來,相對兩邊依次擺上三個雙方棋子,只要將自己的三個棋子走成一條線,對方就算輸了,但是,有很多時候會出現和棋的情況,

二、游戲設計
2.1 棋盤設計
利用字串,在螢屏上列印出一個‘#’號,作為游戲棋盤,(效果圖如下)

2.2 模型設計

三、游戲實作
3.1 SanZiQiMain.c
3.1.1 main(主模塊)
(1)模塊功能及思路:本模塊為程式的入口,通過此模塊調入選單,執行開始游戲或退出游戲的功能,同時也負責rand()函式的配置,rand()函式在之后生成亂數時需要呼叫,配置其的方法是在主模塊中使用時間戳作為srand()函式的引數,這是撰寫本模塊的要點,其它部分的撰寫思路較為簡單,只需利用switch陳述句進行設計即可,
(2)模塊代碼:
int main()
{
int flag = 0;
do
{
srand((unsigned int)time(NULL));
switch (flag = choiceMenu())
{
case 0:printf("退出游戲\n"); break;
case 1:game();break;
default:printf("輸入錯誤,請重新選擇!\n"); break;
}
} while (flag);
return 0;
}
3.1.2 choiceMenu(開始選單)
(1)模塊功能及思路:該函式負責列印游戲開始選單,同時需要回傳玩家的選項值,
(2)模塊代碼:
int choiceMenu()
{
int input = 0;
printf("********************************\n");
printf("***********1. 開始游戲**********\n");
printf("***********0. 退出游戲**********\n");
printf("********************************\n");
printf("請選擇>");
scanf("%d", &input);
return input;
}
3.2 Game.c
3.2.1 game(游戲執行)
(1)模塊功能及思路:本模塊負責游戲的執行,游戲執行的順序為:顯示棋盤——>玩家下棋——>顯示棋盤——>判斷是否贏棋——>電腦下棋——>顯示棋盤——>判斷是否贏棋……該程序在未區分出輸贏之前應處在一個回圈體之中,在此之前,我們還需要一個二維陣列來存放每次下棋操作后的棋子資訊,為了提高代碼的復用性,陣列的行與列采用宏定義的方式進行配置,同時這也是棋盤的行與列,之后將多次使用,為了方便管理,將其定義在Game.h檔案下,
#define ROW 3
#define COL 3
由于顯示棋盤時,需要列印二維陣列中的內容,在第一次顯示棋盤前,應當先對二維陣列進行初始化,將其內部元素均置為‘ ’(空格),
同時,在跳出回圈體后,因根據贏棋判斷函式列印出輸贏資訊,一輪游戲也就到此結束,
(2)模塊代碼:
void game()
{
system("cls");
char ret = 0;
char board[ROW][COL];
boardInit(board, ROW, COL);//初始化陣列
displayBoard(board, ROW, COL);//顯示棋盤
while (1)
{
playerMove(board, ROW, COL);//玩家下棋
displayBoard(board, ROW, COL);//顯示棋盤
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判斷輸贏
computerMove(board, ROW, COL);//電腦下棋
displayBoard(board, ROW, COL);//顯示棋盤
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判斷輸贏
}
if (ret == '*')
{
printf("您贏了\n");
}
else if (ret == '#')
{
printf("您輸了\n");
}
else
{
printf("平局\n");
}
}
3.2.2 boardInit(初始化陣列)
(1)模塊功能及思路:本模塊要執行的是對陣列的初始化,思路也非常簡單,只需要利用回圈對二維陣列進行遍歷即可,
(2)模塊代碼:
void boardInit(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] = ' ';
}
}
}
3.2.3 displayBoard(顯示棋盤)
(1)模塊功能及思路:在撰寫代碼之前,已經設計好了棋盤,本函式只需按照固定格式列印出棋盤即可,難點在于根據行與列的值找到找到列印回圈的規律,列入3x3時,每行列印的資料為3個,只需回圈col次,而每行的分割線‘|’只需列印2次,所以只需要回圈col-1次,列印行分割線時同理,最后一行的資料下面不需要分割線,因此在列印前判斷i是否小于row-1即可,
(2)模塊代碼:
void displayBoard(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++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
3.2.4 playerMove(玩家下棋)
(1)模塊功能及思路:本模塊執行的功能為玩家下棋,只需調整二維陣列中的資料即可,需要注意的是判斷輸入資料是否合法(不超出行與列)與判斷所下位置是否已被占用,
同時,為了取得更好的游玩效果,可以在適當的時候呼叫system("cls")進行清螢屏,使得游玩時顯示的效果就是像在固定的棋盤上放下棋子,而不是重繪整個棋盤,
(2)模塊代碼:
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家走:\n");
while (1)
{
printf("請輸入坐標>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] != ' ')
{
printf("坐標已占用,請重新輸入\n");
}
else
{
board[x - 1][y - 1] = '*';
system("cls");
break;
}
}
else
{
printf("坐標輸入錯誤,請重新輸入\n");
}
}
}
3.2.5 computerMove(電腦下棋)
(1)模塊功能及思路:基本思路與玩家下棋相似,重點在與如何使得計算機的到落子的坐標,這里就要運用到之前提到的rand()函式了,經過配置后,每次呼叫rand()函式會獲取到一個隨機值,而本模塊所需要的隨機值在0~2之間,所以只需利用%運算子即可,同理為了取得更好的游戲效果,添加了清屏代碼與延時代碼Sleep(1000)(用于模擬電腦思考時間),
(2)模塊代碼:
void computerMove(char board[ROW][COL], int row, int col)
{
printf("電腦走:\n");
Sleep(1000);
while (1)
{
int x = rand() % 3;
int y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
system("cls");
break;
}
}
}
3.2.6 isWin(判斷贏棋)
(1)模塊功能及思路:本模塊的回傳值有四個方向:1.玩家贏;2.電腦贏;3.平局;4.游戲繼續,
若在一次落子后,一方取得了勝利,則情況必為三橫行、三豎行、兩斜行中的一種,只需利用判斷陳述句進行判斷即可,同時若玩家獲勝則回傳*,電腦獲勝則回傳#(便于代碼書寫),
若沒有贏棋,則判斷是否平局,只需要遍歷陣列判斷其值是否均不為空格即可,
其它情況則游戲繼續,
(2)模塊代碼:
char isWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int flag = 1;
for (i = 0; i < row; i++)
{
if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][0] == board[i][2])
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[0][i] == board[2][i])
{
return board[0][i];
}
}
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[2][0] == board[0][2])
{
return board[2][0];
}
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
flag = 0;
break;
}
}
}
if (flag)
{
return 'P';
}
return 'C';
//1. 判斷輸贏*/#
//2. 判斷平局P
//3. 游戲繼續C
}
四、游戲測驗






五、游戲代碼
3.1 SanZiQiMain.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Game.h"
int choiceMenu()
{
int input = 0;
printf("********************************\n");
printf("***********1. 開始游戲**********\n");
printf("***********0. 退出游戲**********\n");
printf("********************************\n");
printf("請選擇>");
scanf("%d", &input);
return input;
}
int main()
{
int flag = 0;
do
{
srand((unsigned int)time(NULL));
switch (flag = choiceMenu())
{
case 0:printf("退出游戲\n"); break;
case 1:game();break;
default:printf("輸入錯誤,請重新選擇!\n"); break;
}
} while (flag);
return 0;
}
3.2 Game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Game.h"
void boardInit(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;
for (i = 0; i < row; i++)
{
int j = 0;
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++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家走:\n");
while (1)
{
printf("請輸入坐標>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] != ' ')
{
printf("坐標已占用,請重新輸入\n");
}
else
{
board[x - 1][y - 1] = '*';
system("cls");
break;
}
}
else
{
printf("坐標輸入錯誤,請重新輸入\n");
}
}
}
void computerMove(char board[ROW][COL], int row, int col)
{
printf("電腦走:\n");
Sleep(1000);
while (1)
{
int x = rand() % 3;
int y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
system("cls");
break;
}
}
}
char isWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int flag = 1;
for (i = 0; i < row; i++)
{
if (board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][0] == board[i][2])
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] != ' ' && board[0][i] == board[1][i] && board[0][i] == board[2][i])
{
return board[0][i];
}
}
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[2][0] == board[0][2])
{
return board[2][0];
}
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
flag = 0;
break;
}
}
}
if (flag)
{
return 'P';
}
return 'C';
//1. 判斷輸贏*/#
//2. 判斷平局P
//3. 游戲繼續C
}
void game()
{
system("cls");
char ret = 0;
char board[ROW][COL];
boardInit(board, ROW, COL);//初始化陣列
displayBoard(board, ROW, COL);//顯示棋盤
while (1)
{
playerMove(board, ROW, COL);//玩家下棋
displayBoard(board, ROW, COL);//顯示棋盤
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判斷輸贏
computerMove(board, ROW, COL);//電腦下棋
displayBoard(board, ROW, COL);//顯示棋盤
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}//判斷輸贏
}
if (ret == '*')
{
printf("您贏了\n");
}
else if (ret == '#')
{
printf("您輸了\n");
}
else
{
printf("平局\n");
}
}
3.3 Game.h
#pragma once
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <windows.h>
#define ROW 3
#define COL 3
void game();
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290968.html
標籤:其他
上一篇:【C語言】三字棋小游戲詳解
