我只是在业余时间制作一个简单的扫雷游戏。为了放置地雷,我运行while循环,直到地雷总数==所选级别所需的地雷数量。
但是,我总是得到比预期更多的地雷!我唯一的想法是while循环在多个线程上运行,但是我试图阻止它,但是它仍然会产生比我想要的更多的地雷。我对线程也不是很满意,因为我没有尝试使用它们特别是之前。
我正在使用Processing来简化窗口和绘图的创建。
我尝试了不同的事情。将同步添加到函数负载中,简单的int count = 0;然后每次放置地雷时都会增加计数,这会使情况变得更糟?!?!
private synchronized void placeMines() {
ExecutorService es = Executors.newSingleThreadExecutor();
class placeThread implements Runnable {
Grid grid;
public placeThread(Grid grid) { this.grid = grid; }
public void run() {
final int mines = mode.mines;
//int mCount = 0;
while(this.grid.mineCount() < mines) {
this.grid.addMine();
}
println(grid.mineCount());
}
}
es.execute(new placeThread(this));
}
public synchronized boolean addMine() {
int randX = (int) Math.floor(Math.random() * this.cols);
int randY = (int) Math.floor(Math.random() * this.rows);
Cell selected = getCell(randX, randY);
if(selected.getValue() == 9) {
selected.setValue(9);
return true;
}
return false;
}
public synchronized int mineCount() {
int mCount = 0;
for(ArrayList<Cell> row : this.cells) {
for(Cell c : row) {
if(c.isMine()) mCount++;
}
}
编辑 我更改了代码以使用for循环,并修改了添加地雷的方式
private synchronized void placeMines() {
ExecutorService es = Executors.newSingleThreadExecutor();
class placeThread implements Runnable {
Grid grid;
public placeThread(Grid grid) { this.grid = grid; }
public void run() {
final int mines = mode.mines;
ArrayList<Cell> cList = new ArrayList<Cell>();
for(ArrayList<Cell> row : this.grid.cells) {
cList.addAll(row);
}
for(int j = 0; j < mines; j++) {
int randCell = (int) Math.floor(Math.random() * cList.size());
Cell selected = cList.get(randCell);
if(this.grid.addMine(selected)) { cList.remove(selected); } else { j--; }
}
println(this.grid.mineCount());
}
}
es.execute(new placeThread(this));
}
public synchronized boolean addMine(Cell c) {
if(c.getValue() != 9) {
c.setValue(9);
return true;
}
return false;
}
Cell类(我制作了自己的事件处理系统,因为为什么不这样做:p):
public class Cell extends Interactable {
// value 0 -> 8 is the number of mines around the cell if cell is not a mine.
// value = 9 when the cell is a mine
int xPos, yPos, value, mark;
//gridX and gridY are the coordinates of the cell relative to the grid.
int gridX, gridY;
boolean hidden = true;
boolean flag = false;
boolean wrong = false;
Grid parent;
//Drawing settings
private int border;// = 4; //Border will be set in constructor as a percentage of the cellSize
private int shade = 150;
private int shown = 175;
private int highlight = 200;
public Cell(Grid parent,int gridX, int gridY) {
this.parent = parent;
this.gridX = gridX;
this.gridY = gridY;
this.createHitbox();
this.updatePos();
// Just for when I was testing, this is changed later
this.value = (int) Math.floor(Math.random() * 10);
this.parent.eHandler.register(this, EventList.MouseOver);
this.parent.eHandler.register(this, EventList.MouseLeave);
this.parent.eHandler.register(this, EventList.MouseClicked);
this.parent.eHandler.register(this, EventList.MouseRightClicked);
}
public void die() {
this.parent.eHandler.deregister(this, EventList.MouseOver);
this.parent.eHandler.deregister(this, EventList.MouseLeave);
this.parent.eHandler.deregister(this, EventList.MouseClicked);
this.parent.eHandler.deregister(this, EventList.MouseRightClicked);
}
public void createHitbox() {
this.hitBox = new HitBox(this.xPos, this.yPos, parent.cellSize, parent.cellSize);
}
public synchronized int getValue() {
return this.value;
}
public synchronized void setValue(final int v) {
this.value = v;
}
public void updatePos() {
this.xPos = (parent.cellSize * gridX) + parent.xOffset;
this.yPos = (parent.cellSize * gridY) + parent.yOffset;
this.hitBox.x = this.xPos;
this.hitBox.y = this.yPos;
this.hitBox.w = parent.cellSize;
this.hitBox.h = parent.cellSize;
this.border = parent.cellSize / 10;
}
public synchronized boolean isMine() { return this.value == 9; }
public void draw() {
if(hidden) {
stroke(this.highlight);
strokeWeight(this.border);
fill(this.shade);
rect(this.xPos + this.border / 2, this.yPos + this.border / 2, this.parent.cellSize - this.border, this.parent.cellSize - this.border);
if(this.flag) drawFlag();
} else {
noStroke();
fill(this.shown);
rect(this.xPos, this.yPos, this.parent.cellSize, this.parent.cellSize);
drawValue();
}
}
private void drawValue() {
switch(this.value) {
case 0:
return;
case 1:
fill(10);
break;
case 2:
fill(0, 0, 200);
break;
case 3:
fill(0, 200, 0);
break;
case 4:
fill(200, 0, 0);
break;
case 5:
fill(200, 200, 0);
break;
case 6:
fill(200, 100, 0);
break;
case 7:
fill(100, 0, 200);
break;
case 8:
fill(200, 0, 200);
break;
case 9:
drawMine();
return;
default:
return;
}
textSize(this.parent.cellSize);
textAlign(CENTER, CENTER);
text(this.value, this.xPos + this.parent.cellSize / 2, this.yPos + this.parent.cellSize / 2);
return;
}
private void drawMine() {
stroke(0);
strokeWeight(this.parent.cellSize / 2);
point(this.xPos + this.parent.cellSize / 2, this.yPos + this.parent.cellSize / 2);
}
private void drawFlag() {
stroke(255, 0, 0);
if(wrong) stroke(0, 0, 255);
strokeWeight(this.parent.cellSize / 2);
point(this.xPos + this.parent.cellSize / 2, this.yPos + this.parent.cellSize / 2);
}
public int countMines() {
if(this.isMine()) return 0;
ArrayList<Cell> ns = parent.getNeighbours(this);
int count = 0;
for(Cell c : ns) {
if(c.isMine()) count++;
}
return count;
}
public boolean allMinesFound() {
if(this.isMine()) return false;
ArrayList<Cell> ns = parent.getNeighbours(this);
int mines = 0;
int flags = 0;
for(Cell c : ns) {
if(c.isMine()) mines++;
if(c.flag) flags++;
}
return mines == flags;
}
public void clearChain() {
this.hidden = false;
if(!this.allMinesFound()) return;
for(Cell c : parent.getNeighbours(this)) {
if(c.flag) continue;
boolean wasHidden = c.hidden;
c.reveal(false);
if(c.isMine()) return;
if(c.value == 0 && wasHidden) c.clearChain();
}
}
public void reveal(boolean cce) {
this.hidden = false;
if(this.value == 9) {
//GAMEOVER! MINE!
this.GameOver();
return;
}
if (this.value == 0 && cce == true) {
clearChain();
}
}
@Override
public void onMouseOverEvent() {
this.shade += 20;
this.highlight += 20;
}
@Override
public void onMouseClickedEvent() {
if(!this.hitBox.test(mouseX, mouseY) || !hidden) return;
if(this.flag) return;
this.reveal(true);
}
@Override
public void onMouseRightClickedEvent() {
if(!this.hitBox.test(mouseX, mouseY)) return;
//Mark Loop
if(!hidden) {
clearChain();
return;
}
this.flag = !this.flag;
int fCount = 0;
for(ArrayList<Cell> row : grid.cells) {
for(Cell c : row) {
if(c.flag) fCount++;
}
}
this.parent.parent.flagCount = fCount;
if(this.parent.parent.flagCount >= this.parent.parent.mines) {
this.parent.verifyFlags();
}
}
@Override
public void onMouseLeaveEvent() {
this.shade -= 20;
this.highlight -= 20;
}
private void GameOver() {
this.parent.parent.GameOver();
}
}
答案 0 :(得分:0)
我无法完全解决您的问题,但我会给您一些提示。
围绕while
语句的一般逻辑是可以的。当true
将添加所需的地雷数量时,您的退出条件应为addMine()
:
while(this.grid.mineCount() < mines) {
this.grid.addMine();
}
但是请注意,如果addMine()
和mineCount()
的实现不正确,将无法按预期工作。您没有显示可以解释该问题的Cell
代码。
放置地雷,我运行while循环,直到 地雷==所选级别所需的地雷数量。
使用while
语句进行早期已知的多次迭代是不相关的。
通常,您使用它是因为您不知道必须执行的迭代次数。
如果您知道以下数字,则使用loop
似乎更合适:
for (int i=0; i< mines; i++) {
this.grid.addMine();
}
作为旁注,selected.setValue(9);
在这里似乎没用:
if(selected.getValue() == 9) {
selected.setValue(9);
return true;
}
最后,在使整个应用程序正常工作之前,您可能应该从一些小步骤开始。