运行 定时器完成或取消后的代码
Running a code after Timer finished or Canceled
跟随路径游戏说明:
在这个游戏中,屏幕上有一些方块是不可见的(在我们的例子中是 9 个),它们的随机序列开始出现在屏幕上(我们这里只显示 4 个)。并且用户必须按照方块在屏幕上显示的顺序 select 方块。
有什么问题?:
1. 不应允许用户在显示期间选择方块。我可以禁用按钮,但如何在计时器结束后启用它们?我找不到 postLaunch 或 timerCanceled 事件来再次启用 selection 的按钮?
2. 用户游戏结束后,游戏应在 1 秒内自动重新开始。如果我在 setbackgroundColor() 之后使用 Thread.sleep(1000),它将给我 1 秒但忽略 setBackground()。我希望用户在游戏重置前看到错误的答案(不正确的颜色背景)。
代码:
// allSquares, generatedSquares,generationSpeed can be used to change game difficulty
int allSquares = 9;
int generatedSquares = 4;
int generationSpeed = 500;
Button[] buttons = new Button[allSquares];
@IdRes
int[] ids = {R.id.b1, R.id.b2, R.id.b3, R.id.b4, R.id.b5, R.id.b6, R.id.b7, R.id.b8, R.id.b9};
Button bGenerate;
List<Integer> randomOrder;
int selectedSquare = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bGenerate = findViewById(R.id.bGenerate);
bGenerate.setOnClickListener(this);
}
private void runAlgorithm()
{
// initiate + invisible all squares
for (int i = 0; i < allSquares; i++)
{
buttons[i] = findViewById(ids[i]);
buttons[i].setAlpha(0.0f);
buttons[i].setOnClickListener(this);
buttons[i].setBackgroundColor(getResources().getColor(R.color.squareColor));
buttons[i].setEnabled(false);
}
// generate random sequence
randomOrder = new ArrayList<>();
randomOrder.clear();
Random random = new Random();
while (randomOrder.size() < generatedSquares)
{
int generatedNumber = random.nextInt(allSquares);
if (!randomOrder.contains(generatedNumber))
{
randomOrder.add(generatedNumber);
Log.i("FollowThePath", generatedNumber + "");
}
}
// show random sequence by order
final int[] counter = {0};
selectedSquare = 0;
final Timer timer = new Timer();
timer.schedule(new TimerTask()
{
@Override
public void run()
{
buttons[randomOrder.get(counter[0])].setAlpha(1.0f);
counter[0]++;
if (counter[0] == generatedSquares)
{
timer.cancel();
}
}
}, 0, generationSpeed);
// Bug 1: need to enable buttons after timer finishes, user should not be allowed to choose a square during square reveal
}
@Override
public void onClick(View v)
{
if (v.getId() == R.id.bGenerate)
runAlgorithm();
else
{
Log.i("FollowThePath", v.getTag().toString() + " " + randomOrder.get(selectedSquare));
if (v.getTag().toString().equals(randomOrder.get(selectedSquare).toString()))
{
v.setBackgroundColor(getResources().getColor(R.color.correctColor));
v.setEnabled(false);
selectedSquare++;
} else
{
// Game Over
Toast.makeText(this, "You failed.", Toast.LENGTH_SHORT).show();
// Bug: setBackground executes so fast
v.setBackgroundColor(getResources().getColor(R.color.incorrectColor));
// Bug 2: we need a delay here, so that user sees the incorrect color and gets ready for next game
// Thread.sleep(1000) ignores the color change, it means user can't see incorrectColor even if i add a Thread.sleep after that
// starting a new game
runAlgorithm();
}
if (selectedSquare == generatedSquares)
{
// Succeeded
// Toast.makeText(this,"You did it.",Toast.LENGTH_SHORT).show();
// run a new game
runAlgorithm();
}
}
}
private void enableAllButtons(boolean enable)
{
for (int i = 0; i < allSquares; i++)
{
buttons[i].setEnabled(enable);
}
}
要解决您的第一个问题,因为 TimerTask
完成的唯一方法是根据此条件 counter[0] == generatedSquares
取消它,那么您需要做的就是这样:
@Override
public void run() {
buttons[randomOrder.get(counter[0])].setAlpha(1.0f);
counter[0]++;
if (counter[0] == generatedSquares)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
enableAllButtons(true);
}
});
timer.cancel();
}
}
对于第二个问题,颜色变化可能不会出现,因为重新启动的算法启动得太快,而且所有这些都在 UI 线程上,使用 Thread.sleep(1000)
不会帮助。尝试将 runAlgorithm()
调用包装成类似以下内容:
Handler handler = new Handler();
Runnable r = new Runnable()
{
public void run()
{
//what ever you do here will be done after 500 mili seconds delay.
runAlgorithm();
}
};
handler.postDelayed(r, 500);
希望它有效,因为我无法对其进行测试。
在这个游戏中,屏幕上有一些方块是不可见的(在我们的例子中是 9 个),它们的随机序列开始出现在屏幕上(我们这里只显示 4 个)。并且用户必须按照方块在屏幕上显示的顺序 select 方块。
有什么问题?:
1. 不应允许用户在显示期间选择方块。我可以禁用按钮,但如何在计时器结束后启用它们?我找不到 postLaunch 或 timerCanceled 事件来再次启用 selection 的按钮?
2. 用户游戏结束后,游戏应在 1 秒内自动重新开始。如果我在 setbackgroundColor() 之后使用 Thread.sleep(1000),它将给我 1 秒但忽略 setBackground()。我希望用户在游戏重置前看到错误的答案(不正确的颜色背景)。
代码:
// allSquares, generatedSquares,generationSpeed can be used to change game difficulty
int allSquares = 9;
int generatedSquares = 4;
int generationSpeed = 500;
Button[] buttons = new Button[allSquares];
@IdRes
int[] ids = {R.id.b1, R.id.b2, R.id.b3, R.id.b4, R.id.b5, R.id.b6, R.id.b7, R.id.b8, R.id.b9};
Button bGenerate;
List<Integer> randomOrder;
int selectedSquare = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bGenerate = findViewById(R.id.bGenerate);
bGenerate.setOnClickListener(this);
}
private void runAlgorithm()
{
// initiate + invisible all squares
for (int i = 0; i < allSquares; i++)
{
buttons[i] = findViewById(ids[i]);
buttons[i].setAlpha(0.0f);
buttons[i].setOnClickListener(this);
buttons[i].setBackgroundColor(getResources().getColor(R.color.squareColor));
buttons[i].setEnabled(false);
}
// generate random sequence
randomOrder = new ArrayList<>();
randomOrder.clear();
Random random = new Random();
while (randomOrder.size() < generatedSquares)
{
int generatedNumber = random.nextInt(allSquares);
if (!randomOrder.contains(generatedNumber))
{
randomOrder.add(generatedNumber);
Log.i("FollowThePath", generatedNumber + "");
}
}
// show random sequence by order
final int[] counter = {0};
selectedSquare = 0;
final Timer timer = new Timer();
timer.schedule(new TimerTask()
{
@Override
public void run()
{
buttons[randomOrder.get(counter[0])].setAlpha(1.0f);
counter[0]++;
if (counter[0] == generatedSquares)
{
timer.cancel();
}
}
}, 0, generationSpeed);
// Bug 1: need to enable buttons after timer finishes, user should not be allowed to choose a square during square reveal
}
@Override
public void onClick(View v)
{
if (v.getId() == R.id.bGenerate)
runAlgorithm();
else
{
Log.i("FollowThePath", v.getTag().toString() + " " + randomOrder.get(selectedSquare));
if (v.getTag().toString().equals(randomOrder.get(selectedSquare).toString()))
{
v.setBackgroundColor(getResources().getColor(R.color.correctColor));
v.setEnabled(false);
selectedSquare++;
} else
{
// Game Over
Toast.makeText(this, "You failed.", Toast.LENGTH_SHORT).show();
// Bug: setBackground executes so fast
v.setBackgroundColor(getResources().getColor(R.color.incorrectColor));
// Bug 2: we need a delay here, so that user sees the incorrect color and gets ready for next game
// Thread.sleep(1000) ignores the color change, it means user can't see incorrectColor even if i add a Thread.sleep after that
// starting a new game
runAlgorithm();
}
if (selectedSquare == generatedSquares)
{
// Succeeded
// Toast.makeText(this,"You did it.",Toast.LENGTH_SHORT).show();
// run a new game
runAlgorithm();
}
}
}
private void enableAllButtons(boolean enable)
{
for (int i = 0; i < allSquares; i++)
{
buttons[i].setEnabled(enable);
}
}
要解决您的第一个问题,因为 TimerTask
完成的唯一方法是根据此条件 counter[0] == generatedSquares
取消它,那么您需要做的就是这样:
@Override
public void run() {
buttons[randomOrder.get(counter[0])].setAlpha(1.0f);
counter[0]++;
if (counter[0] == generatedSquares)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
enableAllButtons(true);
}
});
timer.cancel();
}
}
对于第二个问题,颜色变化可能不会出现,因为重新启动的算法启动得太快,而且所有这些都在 UI 线程上,使用 Thread.sleep(1000)
不会帮助。尝试将 runAlgorithm()
调用包装成类似以下内容:
Handler handler = new Handler();
Runnable r = new Runnable()
{
public void run()
{
//what ever you do here will be done after 500 mili seconds delay.
runAlgorithm();
}
};
handler.postDelayed(r, 500);
希望它有效,因为我无法对其进行测试。