我想用C++写tic-tac-toe:
#include <iostream>
#include <vector>
bool X = true;
bool O = false;
bool b = true;
int a = 0;
int j = 100;
std::string game = "";
std::vector<char> c = {'1', '2', '3', '4', '5','6','7','8','9'};
void check(){
std::cout<<"Enter position: ";
int pos;
std::cin>>pos;
if(c.at(pos-1)==pos){
if(X == true){
c[pos-1] = 'X';
O = true;
X = false;
a = 0;
}
else if(O == true){
c[pos-1] = 'O';
X = true;
O = false;
a = 0;
}
}
else{
std::cout<<"Not empty, enter again.";
a = 1;
}
}
void print(){
std::cout<<"|---|---|---|\n| "<<c.at(0)<<" | "<<c.at(1)<<" | "<<c.at(2)<<" | "<<"\n|---|---|---|\n| "<<c.at(3)<<" | "<<c.at(4)<<" | "<<c.at(5)<<" | "<<"\n|---|---|---|\n| "<<c.at(6)<<" | "<<c.at(7)<<" | "<<c.at(8)<<" | \n"<<"|---|---|---|\n";
}
int main(){
print();
int b = 0;
while((X==true||O==true)&&b<9){
check();
while(a=1){
check();
}
print();
for(int i = 0;i<7;i+=3){
if(c.at(i)==c.at(i+1)&&c.at(i+1)==c.at(i+2)&&c.at(i)==c.at(i+2)){
j = i;
break;
}
else{
continue;
}
}
for(int i = 0;i<3;i++){
if(c.at(i)==c.at(i+3)&&c.at(i+3)==c.at(i+6)&&c.at(i)==c.at(i+6)){
j = i;
break;
}
else{
continue;
}
}
if(c.at(0)==c.at(4)&&c.at(4)==c.at(8)&&c.at(0)==c.at(8)){
j = 0;
}
else if(c.at(2)==c.at(4)&&c.at(4)==c.at(6)&&c.at(2)==c.at(6)){
j = 2;
}
if(j!=100){
break;
}
b++;
}
if(j!=100){
if(c.at(j)=='X'){
game = "Won by X!";
}
else{
game = "Won by O!";
}
}
else if(j=100){
game = "Draw";
}
std::cout<<game<<"\n";
}
我一直在犯这个错误:
|---|---|---|
| 1 | 2 | 3 |
|---|---|---|
| 4 | 5 | 6 |
|---|---|---|
| 7 | 8 | 9 |
|---|---|---|
Enter position: terminate called after throwing an instance of
'std::out_of_range'
what(): vector::_M_range_check: __n (which is
18446744073709551615) >= this->size() (which is 9)
所以我创建了两个函数,并在while循环中的main方法中调用它,只要bool X或bool O为true,它就会迭代。
据我所知,错误是在第一个函数中,但我没有看到它有什么问题。
我该怎么修复它?
我的代码的其余部分是否正确?
1条答案
按热度按时间rkue9o1l1#
正如其他人在评论中所解释的那样,你混淆了赋值(=)和相等性(==)的测试。
while(a=1)
应该是while(a==1)
。if(j=100)
应为if(j==100)
在函数
check
(也可以命名为take_turn
)中,测试if(c.at(pos-1)==pos) { ... }
应该是if(c.at(pos-1)-'0'==pos) { ... }
。减去'0'
将c.at(pos-1)
从char
的数值转换为从零开始的整数。这个修复,沿着上面的两个变化,将得到程序运行,所以你可以玩井字游戏。
但是,由于您未能测试用户输入的值,因此需要进行额外的修复。当他/她输入一个无效的位置时,例如,
0
,你的程序将生成一个下标超出范围错误。检查
cin
输入的函数如果有一种简单的方法可以从
cin
获得正确的输入,那不是很好吗?类似于下面代码中的函数
get_int
:以下是运行示例的输出:
在下一次运行时,用户取消。
get_int
应该执行以下算法:1.将一行文本读入字符串。
1.如果字符串为空,则取消输入操作。返回
false
以指示操作已取消。1.修剪字符串开头或结尾处的任何空格。
1.剩下的字符串应该包含一个有效的
int
,没有其他的。不允许在数字之前或之后添加额外的字符。1.用户输入的数字应介于
min
和max
之间(含)。1.如果满足这些条件,则将字符串转换为
int
,并将其存储在参数pos
中。这就是如何将输入值发送回调用例程。返回true
,表示已成功从cin
中提取数字。1.否则,显示错误消息,并要求用户重试。保持循环,直到用户正确地完成它,或者取消它。
下面的函数就是这样工作的:
好好研究这段代码。在你的课本或CppReference上找出你不理解的东西。
int& n
是参考参数。引用是另一个变量的别名。在本例中,n
是调用get_int
时使用的相应参数的别名,即它是pos
的别名。函数get_int
对参数n
所做的任何更改都将自动对调用例程中的变量pos
进行更改。这就是get_int
如何将应答发送回调用例程的方式。for (;;)
是无限循环。唯一的退出(这里)是在执行return
语句时。prompt.empty()
和s.empty()
测试字符串是否为空。std::getline(std::cin, s)
从std::cin
中提取字符,并将其存储在字符串s
中,当遇到'\n'
时停止,但不会将'\n'
存储在字符串s
中。getline
是否成功。这就是if (!std::getline(std::cin, s))
所做的。细节有点棘手。getline
返回std::cin
(或在其调用中使用的任何流对象)。当它被用于if语句(或任何其他需要bool
的上下文)时,std::cin
被隐式转换为!std::cin.fail()
,即“not cin failed”。std::stringstream
是stringstream对象使用的类型。stringstream对象是一个流对象,类似于std::cin
,除了stringstream从字符串中提取字符,而cin
从键盘获取字符。std::stringstream sst(s);
创建一个名为sst
的stringstream对象,并使用字符串s
的内容加载它。sst >> n
从字符串流中提取数字n
,就像std::cin >> n
从键盘中提取数字一样。sst.eof()
测试提取是否因为sst
用完字符而停止。“eof”意思是“文件结束”。在这个程序中,我们希望用完所有字符。当我们这样做时,这意味着数字后面没有任何字符。sst.fail()
测试提取是否失败。这通常是因为sst
在提取有效数字之前遇到了非数字字符或eof。sst >> std::ws;
提取空白,并丢弃它,当遇到eof或非空白字符时停止。std::ws
是一个I/O操作器;查一下。std::ws
来摆脱它,会强制发生以下两件事之一:1.sst
命中eof,在这种情况下我们很高兴。2.sst
没有命中eof,在这种情况下,数字后面有多余的字符。这将触发解析错误。bool parses
和bool is_in_range
是布尔变量。它们用于存储真/假表达式的答案,以便稍后在if语句中使用。sst >> n
导致sst
失败,因为无法从sst
中提取有效数字。当你觉得你可以准确地解释函数
get_int
是如何工作的时候,你应该把这段代码给你的老师看,并解释你是在StackOverflow上找到它的。解释它是如何工作的,让你的老师知道你完全理解它。只有这样,你才应该得到允许,在你的家庭作业中使用类似的东西。