首页 > 其他 > 详细

三子棋游戏

时间:2021-01-28 09:03:18      阅读:27      评论:0      收藏:0      [点我收藏+]
这几天因为发烧所以就没有写博客,现在正式回归学习状态,这几天学习了三子棋的编写,现在我通过分析三子棋代码来巩固所学知识。
三子棋程序考验的是我们对二维数组的使用和理解。
首先我们先从三子棋运行时所进行时的流程来编写test()函数,一个好的开始是成功的一半,先从结构开始思考是一个好习惯,不会让我们在往后编写复杂程序时手忙脚乱。
test()采用分支结构——switch,当选择1时进入game()函数开始游戏,choise = 0时退出游戏,这是退出这个程序的唯一入口。

void test()
{
    int choise = 0;
    srand((unsigned int)time(NULL));
    //菜单,1、开始游戏  0、退出游戏

    //多种选择,采用分支语句switch
    do
    {
        menu();
        printf("请选择要进行的操作:>");
        scanf("%d", &choise);
        switch (choise)
        {
        case 1:
            game();
            break;
        case 0:
            printf("游戏已退出!\n");
            break;
        default:
            printf("非法选项!请重新输入!\n");
        }
    } while (choise);
}

编写菜单函数来说明应该做出什么选择,清晰明了

void menu()
{
    printf("*****************************\n");
    printf("*****1、play     0、exit*****\n");
    printf("*****************************\n");
}

技术分享图片
编写功能函数,首先是初始化board[ROW][COL]二维数组,将这个而二维数组初始化为空格,这样棋盘在整体上是空的状态,视觉上美观一点

void IntiBoard(char board[ROW][COL], int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
            board[i][j] = ‘ ‘;
    }   
}

初始化之后就要打印三子棋棋盘,如下图
技术分享图片
我们把三个空格所以一个主体,所以书写代码 printf(" %c ", board[i][j]),空格之后加一个‘|’,但是首个和末尾不需要加‘|’,所以加入限制条件j < col - 1;
再在底下加入‘---’组成棋盘形状,同理第一行和最后一行不需要‘---’,所以加入限制条件 i < row - 1;

void InputBoard(char board[ROW][COL], int row, int col) 
{
    int i = 0, j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if(j < col - 1)
                printf("|");
        }
        printf("\n");
        for (j = 0; j < col; j++)
        {
            if (i < row - 1)
            {
                printf("---");
                if(j < col - 1)
                    printf("|");
            }
        }
        printf("\n");
    }
}

在编写玩家下棋的代码的时候要注意,一般人在进行游戏时是不会想到‘0,0’这个坐标的,所以board[x - 1][y - 1];
为了不让已经下过的坐标被覆盖,所以我们要加入条件board[x - 1][y - 1] == ‘ ‘,只有满足这个条件才能落子;
具体效果如图
技术分享图片

void PlayerMove(char board[ROW][COL], int row, int col)
{
    int x, y;
    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] == ‘ ‘)
            {
                board[x - 1][y - 1] = ‘*‘;
                break;
            }
            else
            {
                printf("坐标已被占领,请重新选择!\n");
            }
        }
        else
            printf("非法坐标,请重新输入!\n");
    }
}

电脑落子我们是用随机数的方法——rand()来确定电脑落子坐标,当一个随机数 % row时只能够得到低于row的坐标
举个例子:假设row = 3,那么余数就只有0,1,2
小编在编写代码的时候把随机数放在了循环外面,这样虽然也能运行程序,但是当电脑第二次以后落棋有可能显示不出来结果了,因为在循环每次只能获得一个随机数,当board[x][y] == ‘ ‘条件不成立时就陷入死循环了
电脑走的效果图如下
技术分享图片

void ConputerMove(char board[ROW][COL], int row, int col)
{
    int x, y;

    printf("电脑走:>\n");
    Sleep(1000);
    while (1)
    {
        x = rand() % row;
        y = rand() % col;
            if (board[x][y] == ‘ ‘)
            {
                board[x][y] = ‘#‘;
                break;
            }
    }
}

玩家和电脑下棋总要分一个结果,结果有三种:玩家胜利,电脑胜利,平局
返回‘*’——玩家胜利
返回‘#’——电脑胜利
返回‘Q’——平局
返回‘C’——棋盘未满,玩家和电脑继续落子
为了判断棋盘是否满了,我们通过书写is_full()来判断;

int i = 0;
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ‘ ‘)
            return board[i][1];
    }
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ‘ ‘)
            return board[1][i];
    }
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ‘ ‘)
        return board[1][1];
    if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ‘ ‘)
        return board[1][1];
            if (is_full(board, row, col) == 1)
    {
        return ‘Q‘;
    }
    return ‘C‘;
int is_full(char board[ROW][COL], int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ‘ ‘)
                return 0;
        }
    }
    return 1;
}

功能函数书写完毕,接下来书写函数执行顺序使整个代码融会贯通在一起;
要注意的是在玩家和电脑落子之后都要打印棋盘和判断玩家和电脑是否胜出,如有一方胜出就退出循环。
效果如图
技术分享图片

void game()
{
    char board[ROW][COL];
    int win = 0;
    //初始化board为‘ ‘,以此作为棋盘
    IntiBoard(board, ROW, COL);
    InputBoard(board, ROW, COL);
    do
    {
        //玩家走
        PlayerMove(board, ROW, COL);
        //玩家走完之后要打印坐标
        InputBoard(board, ROW, COL);
        win = Check(board, ROW, COL);
        if (win != ‘C‘)
        {
            break;
        }
        //电脑走
        ConputerMove(board, ROW, COL);
        InputBoard(board, ROW, COL);
        win = Check(board, ROW, COL);
        if (win != ‘C‘)
        {
            break;
        }
    } while (1);
    if (win == ‘*‘)
    {
        printf("玩家获胜!\n");
    }
    else if (win == ‘#‘)
    {
        printf("电脑获胜!\n");
    }
    else
    {
    printf("平局!\n");
    }
}

具体代码如下
game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>

#define ROW 3
#define COL 3

void IntiBoard(char board[ROW][COL], int row, int col);
void InputBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ConputerMove(char board[ROW][COL], int row, int col);
int Check(ch

game.c(共159行代码)
其中判断胜负的代码三子棋部分的代码以注释,未注释的是多子棋的部分

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void IntiBoard(char board[ROW][COL], int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
            board[i][j] = ‘ ‘;
    }   
}
void InputBoard(char board[ROW][COL], int row, int col) 
{
    int i = 0, j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if(j < col - 1)
                printf("|");
        }
        printf("\n");
        for (j = 0; j < col; j++)
        {
            if (i < row - 1)
            {
                printf("---");
                if(j < col - 1)
                    printf("|");
            }
        }
        printf("\n");
    }
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
    int x, y;
    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] == ‘ ‘)
            {
                board[x - 1][y - 1] = ‘*‘;
                break;
            }
            else
            {
                printf("坐标已被占领,请重新选择!\n");
            }

        }
        else
            printf("非法坐标,请重新输入!\n");
    }
}
void ConputerMove(char board[ROW][COL], int row, int col)
{
    int x, y;

    printf("电脑走:>\n");
    Sleep(1000);
    while (1)
    {
        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, j;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ‘ ‘)
                return 0;
        }
    }
    return 1;
}
int Check(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][1] == board[i][2] && board[i][1] != ‘ ‘)
            return board[i][1];
    }
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ‘ ‘)
            return board[1][i];
    }
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ‘ ‘)
        return board[1][1];
    if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ‘ ‘)
        return board[1][1];*/

    int i = 0, j = 0;
    //判断行相等
    for (i = 0; i < row; i++)
    {
        int count = 0;
        for (j = 0; j < col - 1; j++)
        {
            if (board[i][j] == board[i][j + 1] && board[i][j] != ‘ ‘)
                count++;
        }
        if (count == col - 1)
            return board[i][j];
    }
    //判断列相等
    for (j = 0; j < col; j++)
    {
         int count = 0;
        for (i = 0; i < row - 1; i++)
        {
            if (board[i][j] == board[i + 1][j] && board[i][j] != ‘ ‘)
                count++;
        }
        if (count == row - 1)
            return board[i][j];
    }
    //判断对角线相等
    int count1 = 0;
    int count2 = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (i == j && board[i][j] != ‘ ‘)
                count1++;
            else if (i + j == row - 1 && board[i][j] != ‘ ‘)
                count2++;
        }

    }
    if (count1 == row)
            return board[0][0];
    if (count2 == row)
            return board[row - 1][0];
    //判断是否平局
    if (is_full(board, row, col) == 1)
    {
        return ‘Q‘;
    }
    return ‘C‘;
}

主函数

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
    printf("*****************************\n");
    printf("*****1、play     0、exit*****\n");
    printf("*****************************\n");
}
void game()
{
    char board[ROW][COL];
    int win = 0;
    //初始化board为‘ ‘,以此作为棋盘
    IntiBoard(board, ROW, COL);
    InputBoard(board, ROW, COL);
    do
    {
        //玩家走
        PlayerMove(board, ROW, COL);
        //玩家走完之后要打印坐标
        InputBoard(board, ROW, COL);
        win = Check(board, ROW, COL);
        if (win != ‘C‘)
        {
            break;
        }
        //电脑走
        ConputerMove(board, ROW, COL);
        InputBoard(board, ROW, COL);
        win = Check(board, ROW, COL);
        if (win != ‘C‘)
        {
            break;
        }
    } while (1);
    if (win == ‘*‘)
    {
        printf("玩家获胜!\n");
    }
    else if (win == ‘#‘)
    {
        printf("电脑获胜!\n");
    }
    else
    {
        printf("平局!\n");
    }
}
void test()
{
    int choise = 0;
    srand((unsigned int)time(NULL));
    //菜单,1、开始游戏  0、退出游戏

    //多种选择,采用分支语句switch
    do
    {
        menu();
        printf("请选择要进行的操作:>");
        scanf("%d", &choise);
        switch (choise)
        {
        case 1:
            game();
            break;
        case 0:
            printf("游戏已退出!\n");
            break;
        default:
            printf("非法选项!请重新输入!\n");
        }
    } while (choise);
}
int main()
{
    test();
    return 0;
}

到此为止三子棋的学习结束!
如有缺漏或者错误望大家评论指出!!!!!

三子棋游戏

原文:https://blog.51cto.com/15083094/2608521

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!