三子棋是一種民間傳統游戲,又叫九宮棋、圈圈叉叉、一條龍、井字棋等,將正方形對角線連起來,相對兩邊依次擺上三個雙方棋子,只要將自己的三個棋子走成一條線,對方就算輸了,但是,有很多時候會出現和棋的情況,
我們學習c語言也有一段時間了,現在我們嘗試自己用C語言寫一個三子棋小游戲玩玩吧!
前期準備:
工程檔案思路:
主函式放到ticktacktoe(三子棋)中
三子棋具體的實作放到game.c / game.h中

主函式游戲思路:
三子棋游戲思路:
1、至少玩一次,可以玩多次,do…while回圈
2、進入游戲后先列印選單提示
3、提示用戶輸入,根據輸入值來確定后續的游戲行程(1代表玩游戲,0代表退出,其他需要重新選擇
三子棋玩游戲的思路:
首先我們要知道三子棋的一些資訊:
1、三子棋形狀


2、游戲規則:同一形狀連成直線(三格)即獲勝
所以獲勝的條件:1、橫排同形狀 2、豎排同形狀 3、對角線同形狀
三子棋游戲實作具體思路:
1.我們要記錄下棋的結果,就需要對應的二維陣列來存盤
2.創建的二維陣列要進行初始化,賦值成空格" "
3.列印棋盤,看一下展示的效果

- 游戲狀態判斷 四種狀態 玩家贏,電腦贏,平局,繼續
4.玩家下棋
5.判斷玩家是否游戲勝利 判斷游戲狀態是否繼續
6.電腦下棋(隨機落子的方式)
7.判斷電腦是否游戲勝利 判斷游戲狀態是否繼續
可優化點
1.電腦走可優化,將隨機走變成有策略走,讓電腦看起來更像“玩家”,(代碼中實作了這個優化)

2.判斷游戲進展部分可優化,比如說后續ROW,COL都改成4,也就是將三子棋變成四子棋,本程式中的游戲進展部分也需要調整了,為了讓ROW,COL在變化調整后依然適用,我們可以對其進行相應的優化,(本次代碼暫未實作該優化)
優化1實作:
思路:這個優化的實作注意考慮兩個方面的內容:
1、如果電腦落子,有機會直接贏,則優先落在能贏的坐標上
2、如果玩家落子有機會贏,攔截玩家路子坐標(步驟1優先級高于步驟2)
3、如果步驟1、步驟2均不滿足,電腦繼續偽隨機落子
原始碼下載及效果展示:
三子棋游戲github原始碼
效果展示:

完整代碼:
源檔案ticktacktoe.c內容
/*******************/
//以下是源檔案ticktacktoe.c內容
/*******************/
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game_menu(void)
{
printf("*********************************\n");
printf("********* 1.play game ***********\n");
printf("********* 0.exit game ***********\n");
printf("*********************************\n");
}
void play_game(void)
{
char board[ROW][COL] = { 0 };//創建二維陣列來存盤棋盤下棋資料
Init_board(board, ROW, COL);//初始化棋盤
Display_board(board, ROW, COL);//列印棋盤
char ret = 0;//接收游戲進行的進展
//玩家贏:* 電腦贏:# 平局:Q 繼續:C
while (1)
{
Player_move(board, ROW, COL);//玩家下棋
Display_board(board, ROW, COL);//列印棋盤
ret = Is_win(board, ROW, COL);//判斷游戲是否繼續
if (ret != 'C')
break;
Computer_move(board, ROW, COL);//電腦下棋
Display_board(board, ROW, COL);//列印棋盤
ret = Is_win(board, ROW, COL);//判斷游戲是否繼續
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("恭喜你,玩家贏得游戲!\n");
}
else if (ret == '#')
{
printf("很遺憾,電腦贏得游戲!\n");
}
else if (ret == 'Q')
{
printf("這把平局,還差一點點就贏了哦!\n");
}
Display_board(board, ROW, COL);//列印棋盤
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
game_menu();//列印游戲選單
printf("請選擇:>>");
scanf("%d", &input);
switch (input)
{
case 1:
play_game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,請重選\n");
break;
}
} while (input);
return 0;
}
頭檔案game.h內容
/*******************/
//以下是頭檔案game.h內容
/*******************/
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//定義行號和列號
#define ROW 3
#define COL 3
//初始化棋盤宣告
void Init_board(char board[ROW][COL], int row, int col);
//列印棋盤宣告
void Display_board(char board[ROW][COL], int row, int col);
//玩家下棋宣告
void Player_move(char board[ROW][COL], int row, int col);
//電腦下棋宣告
void Computer_move(char board[ROW][COL], int row, int col);
//判斷游戲進展
char Is_win(char board[ROW][COL], int row, int col);
//判斷電腦能否贏
int Check_computer(char board[ROW][COL], int row, int col);
//判斷玩家能否贏
int Judge_player(char board[ROW][COL], int row, int col, int k);
源檔案game.c內容
/*******************/
//以下是源檔案game.c內容
/*******************/
#include"game.h"
//實作初始化棋盤
void Init_board(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++)
{
board[i][j] = ' ';
}
}
}
//實作列印棋盤
void Display_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)//列印row行,將棋盤一行 + ___看作一行列印內容
{
for (j = 0; j < col; j++)//列印col列
{
printf(" %c ", board[i][j]);//將 %c 看作一個列印單位
if (j < col - 1)//一行就前col-1個需要列印|,最后一個不列印
printf("|");
}
printf("\n");//一行內容列印完后換行
if (i < row - 1)//最后一行不列印
{
for (j = 0; j < col; j++)
{
printf("---");//將___視為一個整體
if (j < col - 1)//一行就前col-1個需要列印|,最后一個不列印
printf("|");
}
}
//printf("___|___|___\n");//這種列印方式僅能列印三行三列的棋盤,不推薦
printf("\n");//一行內容列印完后換行
}
}
//實作玩家下棋
void Player_move(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] == ' ')//玩家輸入的1 1 對應的下標其實是 0 0
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐標已被占用,請重新輸入\n");
}
}
else
{
printf("坐標輸入錯誤,請重新輸入\n");
}
}
}
//實作電腦下棋
//void Computer_move(char board[ROW][COL], int row, int col)
//{
//
// while (1)
// {
// int x = rand() % row;
// int y = rand() % col;
// if (board[x][y] == ' ')
// {
// board[x][y] = '#';
// break;
// }
// }
//}
int Judge_player(char board[ROW][COL], int row, int col, int k)
{
//下面這個函式就是判斷玩家是否有機會贏,如果能贏就堵住他
int i = 0;
int j = 0;
while (0 == k)
{
//判斷玩家在橫行上是否會贏
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '*' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}
if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}
if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
if (k != 0)
break;
//判斷玩家在豎列上是否會贏
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '*' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}
if (board[0][j] == board[2][j] && board[2][j] == '*' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}
if (board[1][j] == board[2][j] && board[2][j] == '*' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;
}
//判斷玩家在對角線上是否會贏,又加了一個while是為了讓判斷對角線的代碼成塊,
while (0 == k)
{
if (board[0][0] == board[1][1] && board[1][1] == '*' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}
if (board[0][0] == board[2][2] && board[2][2] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}
if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}
if (board[0][2] == board[2][0] && board[2][0] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][0] && board[2][0] == '*' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
break;
}
return k;//回傳值如果是1那么已經對玩家進行了阻攔,如果是0則無需阻攔,
}
int Check_computer(char board[ROW][COL], int row, int col)//判斷電腦下一步落子能否贏游戲
{
int i = 0;
int j = 0;
int k = 0;
while (k == 0)
{
//判斷電腦行排能否贏
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][0] == '#' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}
if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}
if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
if (k != 0)//落子后跳出
break;
//判斷電腦列排能否贏
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[0][j] == '#' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}
if (board[0][j] == board[2][j] && board[0][j] == '#' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}
if (board[2][j] == board[1][j] && board[0][j] == '#' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;
}
//判斷電腦對角線能否贏
while (0 == k)
{
//左上角到右下角對角線判斷
if (board[0][0] == board[1][1] && board[0][0] == '#' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}
if (board[0][0] == board[2][2] && board[0][0] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][2] && board[0][0] == '#' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}
//左下角到右上角對角線判斷
if (board[2][0] == board[1][1] && board[2][0] == '#' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
if (board[2][0] == board[0][2] && board[2][0] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}
break;
}
k = Judge_player(board, row, col, k);
return k;
}
//實作電腦下棋優化
void Computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
int ret = 0;
ret = Check_computer(board, row, col);
while (0 == ret)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判斷棋盤是否滿了
int Is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
count++;
}
}
if (count == 0)
return 1;
else
return 0;
}
//實作判斷游戲進展
char Is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判斷三行
for (i = 0; i < row; i++)
{
if ((board[i][0] == board[i][1]) && (board[i][0] == board[i][2]) && (board[i][0] != ' '))
{
return board[i][0];
}
}
//判斷三列
for (i = 0; i < row; i++)
{
if ((board[0][i] == board[1][i]) && (board[0][i] == board[2][i]) && (board[0][i] != ' '))
{
return board[0][i];
}
}
//判斷兩條對角線
if ((board[0][0] == board[1][1]) && (board[0][0] == board[2][2]) && (board[0][0] != ' '))
{
return board[0][0];
}
if ((board[0][2] == board[1][1]) && (board[0][2] == board[2][0]) && (board[0][2] != ' '))
{
return board[0][2];
}
//判斷平局 棋盤滿了回傳1,不滿回傳0
int ret = Is_full(board, row, col);
if (ret == 1)
return 'Q';
else
return 'C';
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280290.html
標籤:其他
