simulate a combination lock

Simulate a Combination Lock

Description

Specify, design, and implement a class that can be used in a program that simulates a combination lock. The lock has a circular knob, with the numbers 0 through 39 marked on the edge, and it has a three-number combination, which we’ll call x, y, z. To open the lock, you must turn the knob clockwise at least one entire revolution, stopping with x at the top; then turn the knob counter-clockwise, stopping the second time that y appears at the top; finally turn the knob clockwise again, stopping the next time that z appears at the top. At this point, you may open the lock.
Your lock class should have a constructor that initializes the three-number combination(use 0, 0, 0 for default arguments). Also provide member functions:
( a ) to alter the lock’s combination to a new three-number combination
( b ) to turn the knob in a given direction until a specified number appears at the top
( c ) to close the lock
( d ) to attempt to open the lock
( e ) to inquire about the status of the lock(open or shut)
( f ) to tell you what number is currently at the top

Analysis

This question is located in p120 of Data Structures and Other Objects Using C++(Fourth Edition).
According to the tips from the question, we should design a class to implement a combination lock. To design a class, class member variables and member functions must be taken into consideration.
These questions are not so difficult. I am aimed at practicing my English writing and review the knowledge of software engineering. Pay more effort to the design and documentation instead of codes.

Class Design

Complete a class and draw the class diagram.

Class member variables

To indicate the current value of x, y, z respectively, we declare them as private variables.
To indicate whether the user has turned the knob clockwise one revolution and adjust x, y, z in sequence, we declare a bool variable called has_right_operation_sequence. We need to check it when we attempt to open the clock. To support us in checking the value of has_right_operation_sequence, we declare adjust_one_revolution, adjust_x, adjust_y( both of them are bool variables).
Additionally, we need a integrated value called top to indicate the current value of top. To check whether our tuple is matched with the correct key of the combination lock, we are supposed to declare a structure to hold the key.

Class member operations

I think I need these operation below referenced to a-f:
When it comes to the constructor, we have both a default constructor and a overloaded constructor which receives three integrated values as its arguments. They are:
combination_lock();
combination_lock(int, int, int);
( a )
void turn_knob_clockwise_one_revolution();
int alter_x_to_top();
int alter_y_to_top();
int alter_z_to_top();
( b )
void set_top_val(int val);
If the val is less than 0, it will not pass the assertion. If the val is larger than 39, it will be set to the remaining value after being divided. The actual value called α \alpha α is calculated as below.
α = v a l   m o d   40 \alpha = val\,mod\,40 α=valmod40
( c )
void close_lock();
( d )
int attempt_open_lock();
void initialize_key(int, int, int);
( e )
int lock_status();
( f )
int get_top_val();

Class diagram

This diagram is generated by visual studio 2017.
class diagram

Flow design

A Simple Flowchart

According to the description of the question, I attempt to draw a flow diagram using UML.

Created with Raphaël 2.2.0 start turn clockwise one revolution set top and adjust x set top and adjust y set top and adjust z confirm? Right sequence? end yes no

Implementation

Header File

// lock.h
#pragma once
struct lock_key {
	int i;
	int j;
	int k;
};

enum lock_status { OPEN, SHUT };

class combination_lock {
public:
	combination_lock() {
		int x = 0;
		int y = 0;
		int z = 0;
		int top = 0;
	};
	combination_lock(int m, int n, int p) {
		int x = m;
		int y = n;
		int z = p;
		int top = 0;
	};
	void turn_knob_clockwise_one_revolution();
	int alter_x_to_top();
	int alter_y_to_top();
	int alter_z_to_top();
	void set_top_val(int);
	void close_lock();
	int attempt_open_lock();
	int lock_status();
	int get_top_val();
	void initialize_key(int, int, int);
private:
	int x, y, z, top;
	bool has_right_operation_sequence = false;
	bool adjust_one_revolution = false;
	bool adjust_x = false;
	bool adjust_y = false;
	int status = SHUT;
	lock_key key;
};

Source File

// lock.cpp
#include "pch.h"
#include "lock.h"
#include <iostream>
#include <assert.h>

void combination_lock::turn_knob_clockwise_one_revolution()
{
	adjust_one_revolution = true;
}

int combination_lock::alter_x_to_top()
{
	assert(adjust_one_revolution);
	adjust_x = true;
	x = top;
	return 0;
}

int combination_lock::alter_y_to_top()
{
	assert(adjust_one_revolution && adjust_x);
	adjust_y = true;
	y = top;
	return 0;
}

int combination_lock::alter_z_to_top()
{
	assert(adjust_one_revolution && adjust_x && adjust_y);
	has_right_operation_sequence = true;
	z = top;
	return 0;
}

void combination_lock::set_top_val(int val)
{
	top = val % 40;
}

void combination_lock::close_lock()
{
	status = SHUT;
}

int combination_lock::attempt_open_lock()
{
	assert(has_right_operation_sequence);
	if ((key.i == x) && (key.j == y) && (key.k == z)) {
		status = OPEN;
		return 0;
	}
	else {
		status = SHUT;
		return -1;
	}
}

int combination_lock::lock_status()
{
	return status;
}

int combination_lock::get_top_val()
{
	return top;
}

void combination_lock::initialize_key(int m, int n, int q)
{
	key.i = m;
	key.j = n;
	key.k = q;
}

Test

Case 1

#include "pch.h"
#include "lock.h"
#include <iostream>
/*
 * incorrect combination of x, y, z
 */
int main()
{
	combination_lock a;
	a.initialize_key(1, 2, 3);
	a.turn_knob_clockwise_one_revolution();
	std::cout << "Before operation:\n";
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	a.set_top_val(1);
	a.alter_x_to_top();
	a.set_top_val(2);
	a.alter_y_to_top();
	a.set_top_val(43);
	a.alter_z_to_top();
	std::cout << "After operation:\n";
	if (a.attempt_open_lock() == 0) {
		std::cout << "succeeded to open!\n";
	}
	else {
		std::cout << "failed to open!\n";
	}
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	std::cout << "lock it\n";
	a.close_lock();
	return 0;
}

output(succeed to open):
success

Case 2

#include "pch.h"
#include "lock.h"
#include <iostream>
/*
 * incorrect combination of x, y, z
 */
int main()
{
	combination_lock a;
	a.initialize_key(1, 2, 3);
	a.turn_knob_clockwise_one_revolution();
	std::cout << "Before operation:\n";
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	a.set_top_val(1);
	a.alter_x_to_top();
	a.set_top_val(35);
	a.alter_y_to_top();
	a.set_top_val(43);
	a.alter_z_to_top();
	std::cout << "After operation:\n";
	if (a.attempt_open_lock() == 0) {
		std::cout << "succeeded to open!\n";
	}
	else {
		std::cout << "failed to open!\n";
	}
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	std::cout << "lock it\n";
	a.close_lock();
	return 0;
}

output(incorrect combination):
fail because of incorrect combination

Case 3

#include "pch.h"
#include "lock.h"
#include <iostream>

/* 
 * forget to turn knob clockwise one revolution before operating
 */

int main()
{
	combination_lock a;
	a.initialize_key(1, 2, 3);
	std::cout << "Before operation:\n";
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	a.set_top_val(1);
	a.alter_x_to_top();
	a.set_top_val(2);
	a.alter_y_to_top();
	a.set_top_val(43);
	a.alter_z_to_top();
	std::cout << "After operation:\n";
	if (a.attempt_open_lock() == 0) {
		std::cout << "succeeded to open!\n";
	}
	else {
		std::cout << "failed to open!\n";
	}
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	std::cout << "lock it\n";
	a.close_lock();
	return 0;
}

output(wrong operation sequence, an assertion error occurred):
在这里插入图片描述

Conclusion

Design is important.

Reference

整理自 Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Memories off

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值