30/09/2018, 20:08

Game cờ caro 3x3 sau 4 ngày học C++, xin góp ý chỉnh sửa

Em mới tự học C++ được 4 ngày. Hôm qua, em vừa viết được trò cờ caro 3x3 2 người chơi, em định mở rộng bảng nhưng thấy cách làm của mình bị dài quá mà khó mở rộng. Đây là code em viết xin mọi người góp ý chỉnh sửa:

#include <iostream>

using namespace std;

int main()
{
    char choice2;
    char xo;
    int choice;
    string plr1;
    string plr2;
    char a =' '; char b= ' '; char c= ' '; char d = ' '; char e = ' '; char f= ' '; char g= ' '; char h = ' '; char i= ' ';


    //INTRODUCTION - cin player's names
    START:
    cout << "3x3 - 2 PLAYERS - CARO BOARD (Use NumPad for optimal gameplay)" << endl;
    cout << endl;
    cout << endl;
    cout << endl;
    cout << "Insert player 1's name (No space between characters)" << endl;
    cin >> plr1;
    cout << endl;
    cout << "Insert player 2's name (No space between characters)" << endl;
    cin >> plr2;
    cout << endl;
    //GAMEPLAY

    cout << " ___________________" << endl;
    cout << " | (7) | (8) | (9) |" << endl;
    cout << " |_____|_____|_____|" << endl;
    cout << " | (4) | (5) | (6) |" << endl;
    cout << " |_____|_____|_____|" << endl;
    cout << " | (1) | (2) | (3) |" << endl;
    cout << " |_____|_____|_____|" << endl;
    cout << endl;
    cout << endl;


    for ( int k = 1; k < 10 ; k ++) {

        if ( k % 2 == 0) {
            cout << ""<<plr1<<"'s turn " << endl;
            xo = 'X';
        }
        else {
            cout << ""<<plr2<<"'s turn " << endl;
            xo = 'O';
        }
        cout << "Please make your choice by selecting the appropriate number (Use NumPad for optimal gameplay)" << endl;
        cin >> choice;
        switch (choice) {
                case 7:
                    a=xo;
                    break;
                case 8:
                    b=xo;
                    break;
                case 9:
                    c=xo;
                    break;
                case 4:
                    d=xo;
                    break;
                case 5:
                    e=xo;
                    break;
                case 6:
                    f=xo;
                    break;
                case 1:
                    g=xo;
                    break;
                case 2:
                    h=xo;
                    break;
                case 3:
                    i=xo;
                    break;
                default:
                    cout << "ERROR: Pick the number within range" << endl;
                    break;
        }

        cout << " ___________________" << endl;
        cout << " |  "<<a<<"  |  "<<b<<"  |  "<<c<<"  |" << endl;
        cout << " |_____|_____|_____|" << endl;
        cout << " |  "<<d<<"  |  "<<e<<"  |  "<<f<<"  |" << endl;
        cout << " |_____|_____|_____|" << endl;
        cout << " |  "<<g<<"  |  "<<h<<"  |  "<<i<<"  |" << endl;
        cout << " |_____|_____|_____|" << endl;
        cout << endl;
        cout << endl;

        if ( a == 'X' && b == 'X' && c == 'X' || d == 'X' && e == 'X' && f == 'X' || g == 'X' && h == 'X' && i == 'X' ||
             a == 'X' && d == 'X' && g == 'X' || b == 'X' && e == 'X' && h == 'X' || c == 'X' && f == 'X' && i == 'X' ||
             a == 'X' && e == 'X' && i == 'X' || g == 'X' && e == 'X' && c == 'X' ) {
                cout << "   "<<plr1<<" WON!!! " << endl;
                goto QUESTION;
                }
        else if ( a == 'O' && b == 'O' && c == 'O' || d == 'O' && e == 'O' && f == 'O' || g == 'O' && h == 'O' && i == 'O' ||
                a == 'O' && d == 'O' && g == 'O' || b == 'O' && e == 'O' && h == 'O' || c == 'O' && f == 'O' && i == 'O' ||
                a == 'O' && e == 'O' && i == 'O' || g == 'O' && e == 'O' && c == 'O' )   {
                cout << "   "<<plr2<<" WON!!! " << endl;
                goto QUESTION;
                }
    }
    cout << "It's a Draw" << endl;

    QUESTION:
        cout << " Do you want to play again? <y/n>" << endl;
        cin >> choice2;
        switch (choice2)
            case 'y' :
                goto START;


    return 0;
}

Ngô Doãn Tuấn viết 22:19 ngày 30/09/2018

Hay Lắm Bạn Ơi
Cố gắng nhé

Ngoc Duy Nguyen viết 22:14 ngày 30/09/2018

Bạn có góp ý gì về code của mình không? Mình thấy game đơn giản mà code dài quá, không biết có chỗ nào rút gọn được không?

Ngô Doãn Tuấn viết 22:23 ngày 30/09/2018

if ( a == ‘X’ && b == ‘X’ && c == ‘X’ || d == ‘X’ && e == ‘X’ && f == ‘X’ || g == ‘X’ && h == ‘X’ && i == ‘X’ ||
a == ‘X’ && d == ‘X’ && g == ‘X’ || b == ‘X’ && e == ‘X’ && h == ‘X’ || c == ‘X’ && f == ‘X’ && i == ‘X’ ||
a == ‘X’ && e == ‘X’ && i == ‘X’ || g == ‘X’ && e == ‘X’ && c == ‘X’ ) {
cout << " “<<plr1<<” WON!!! " << endl;
goto QUESTION;
}
else if ( a == ‘O’ && b == ‘O’ && c == ‘O’ || d == ‘O’ && e == ‘O’ && f == ‘O’ || g == ‘O’ && h == ‘O’ && i == ‘O’ ||
a == ‘O’ && d == ‘O’ && g == ‘O’ || b == ‘O’ && e == ‘O’ && h == ‘O’ || c == ‘O’ && f == ‘O’ && i == ‘O’ ||
a == ‘O’ && e == ‘O’ && i == ‘O’ || g == ‘O’ && e == ‘O’ && c == ‘O’ ) {
cout << " “<<plr2<<” WON!!! " << endl;
goto QUESTION;
}
}

Nếu tối ưu thì đoạn này bị lặp code
Mình nghĩ vậy. Bạn có thể cho vào hàm

Ngoc Duy Nguyen viết 22:18 ngày 30/09/2018

Bạn thử chỉ mình xem làm ví dụ được không?

hacked viết 22:12 ngày 30/09/2018

Bạn chưa xử lý trường hợp người chơi chơi vào ô đã có.

... viết 22:18 ngày 30/09/2018

Khi nào bạn học đến lập trình hướng đối tượng, bạn sẽ làm được cái này một cách dài hơn…
nhưng dễ hơn.
Khi đó bàn cờ sẽ là một đối tượng riêng biệt không phụ thuộc vào nước cờ của người chơi, muốn nó to bao nhiêu cũng được.

Ngoc Duy Nguyen viết 22:22 ngày 30/09/2018

@sample Đúng rồi nhỉ, để mình xem xét lại

Ngoc Duy Nguyen viết 22:18 ngày 30/09/2018

@nguyenchiemminhvu Cái này chắc phải lâu nữa mình mới động đến. 4 ngày mình mới học xong các vòng lặp và function, include header file thôi. Mình mới lớp 10 nên còn nhiều thời gian mà mày mò lắm

Nguyễn Đình Nam viết 22:17 ngày 30/09/2018

Game hay lắm … bạn thử dùng mảng 2 chiều xem… có thể rút gọn đc dấy,
có lỗi ở đoạn … 2 người cùng nhập là 5 thì … dấu X sẽ chuyển thành dấu O , (ngược lại);

Nguyen Quang Hien viết 22:22 ngày 30/09/2018

Bạn lưu quân cờ vào biến kiểu này rất khó để mở rộng.
Để phát triển lớn hơn. Cần sử dụng object array, và 1 mảng 2 chiều làm bàn cờ. Noí chung sẽ khó hơn rất nhiều .

Đỗ Văn Chanh viết 22:14 ngày 30/09/2018

b đang là sv hay là gì mà đã làm như thế này rồi

Ngoc Duy Nguyen viết 22:23 ngày 30/09/2018

@Nguyen_Dinh_Nam @quanghien95 Mình chưa học đến Array , mảng 2 chiều các bạn ơi, Mới học loop và tạo function, include header file thôi à. Khi nào học đến thì mình edit lại code nhé.

Ngoc Duy Nguyen viết 22:18 ngày 30/09/2018

@chanhbc Mình lớp 10 (post xưng hô bằng “em” mà), mới học C++ thôi, chưa phải sinh viên đại học đâu.

Đỗ Văn Chanh viết 22:16 ngày 30/09/2018

lại giỏi trước tuổi rồi

Trương Phước Hiệu viết 22:19 ngày 30/09/2018

Mới lớp 10 học 4 ngày như thế là giỏi rồi, tích cực luyện c++ vào đại học thi acm là vừa. hoặc học pascal để thi olympic phổ thông

Maskma viết 22:20 ngày 30/09/2018

Nhận xét
Nếu bạn ms học đc c++ 4 ngày (mà trc đó chưa học lập trình hoặc lâp trình nhiều) thì thế này là rất tốt rồi.
Một vài gợi ý
Mình sẽ đưa ra 1 vài gợi ý cho bạn để hoàn thiện trò chơi (mình sẽ tổng hợp lại cả 1 số ý kiến ở trên):

  1. Sử dụng mảng 2 chiều để lưu trạng thái các ô thay vì dùng các a, b, c, d,… Việc này giúp cho bạn khai báo ngắn gọn, có thể mở rộng bàn cờ tuỳ ý, thuận lợi cho việc kiểm tra và xử lí với các ô.
  2. Vì mỗi ô cờ giống nhau nên bạn ko cần phải cout nhiều lần để vẽ hết cả bàn cờ. Hãy dùng vòng lặp và thử in ra bàn cờ MxN với M, N là 2 số nhập vào. Thử xem
  3. Khi sử dụng mảng 2 chiều thì theo mình có 2 cách để bạn cho người chơi nhập vị trí:
  • cho họ nhập 2 chỉ số i, j là vị trí hàng và vị trí cột (như trong toán thì kiểu đây là toạ độ ý). Với cách này bạn nên vẽ thêm 2 cột ở rìa bàn cờ điền các số để ng chơi nhìn dễ dàng dóng xuống và biết đc chỉ số của ô muốn chọn.
  • cách 2 (Khó hơn) là cho họ sử dụng các phím mũi tên để di chuyển cái nhấp nháy ý, khi cái nhấp nháy đến ô nào và họ chọn (bấm Space chẳng hạn) thì ô đó đc điền. Cách này giúp ng chơi dễ hơn nhưng mình lại bị khó hơn
  1. Ở phần xét thắng thua của bạn, ở đây là bàn cờ 3x3 nên mới có 16 TH thắng xảy ra nên bạn có thể tự code chay đc chứ nếu bàn cờ 10x10 thì bạn làm thế nào. 1 phép tính đơn giản để tính số TH (mình tự nghĩ): 4(n-c+1)(m-c+1) + (c-1)(n+m-2c+2) trong đó m, n là kích thước bàn cờ, c là số xo liên tiếp cần để thắng. Nếu là mxn = 10x10, c = 5 thì số TH = 4(10-5+1)(10-5+1) + (5-1)(10+10-2.5+2) = 192(đây mới là TH thắng của 1 ng, 2 ng sẽ là 384) Bạn code đc hết chứ?
    Giờ ta đã có mảng 2 chiều, bạn có thể dùng vòng lặp để duyệt từng ô, hãy nghĩ ở mỗi ô bạn xét cái gì để biết có ai thắng ko?
    Đó đây là 1 số gợi ý nhỏ (thực ra ko nhỏ lắm), hãy thử thách mình xem làm đc ko nhé. Cứ tiếp tục học theo cách này đi, vừa làm các trò chơi vừa học rất hữu ích!
    bị bí chỗ nào bạn cứ hỏi mình và mọi ng sẽ trả lời
Ngoc Duy Nguyen viết 22:13 ngày 30/09/2018

@Maskma Cảm ơn bạn nhiều, mình chưa học mảng 2 chiều nên chưa hiểu lắm về cái này. Để mình tìm hiểu thêm rồi edit lại code. Sau này làm GUI với tạo đối thủ AI là xong ứng dụng

Maskma viết 22:24 ngày 30/09/2018

trc tiên cứ học mảng 2 chiều xong áp dụng đc là ngon rồi. GUI với AI cứ để sau vì 2 cái đấy phải học thêm nhiều thứ -> dễ nản đấy
Bước chậm mà chắc còn hơn. Trc mình cũng ms làm đc tí đã muốn GUI đẹp, xong “tự nghĩ” thuật toán AI xong ~~> fail

Ngoc Duy Nguyen viết 22:16 ngày 30/09/2018

@Maskma
Cho mình hỏi bạn có cách tư duy nào để nghĩ ra công thức tính số trường hợp thắng cờ này

4(n-c+1)(m-c+1) + (c-1)(n+m-2c+2)

Bạn lý giải công thức được không vì mình không hiểu lắm, theo mình nghĩ (n-c+1)(m-c+1) là số khả năng theo 2 chiều dọc và ngang, vậy bạn tính số trường hợp theo chiều chéo như thế nào vậy?

Gió viết 22:21 ngày 30/09/2018

Theo mình số TH thắng ở đường chéo là 2*(m-c+1)*(n-c+1) Giả sử xét 1 đường chéo chính từ ô 0;0 nó có thể di chuyển sang trái là n-c+1 ô, sang phải là m-c+1 ô nên số khả năng thắng ở đường chéo chính = chéo phụ =(m-c+1)(n-c+1)
Cách tính số th thắng ở hàng, cột mình nghĩ là. Xét ở 1 hàng thì số th thắng có thể có là (n-c+1) như vậy m hàng sẽ có m*(n-c+1) cách thắng theo hàng ngang và tương tự có n*(m-c+1) cách thắng theo chiều dọc

Bài liên quan
0